From: Frankque
Subject: distinction?
Date: 
Message-ID: <3a2962c9@news.infinetgroup.com>
Hi! Guru here:

I know Scheme is a dialect of Lisp. But I want know exactly the point(s)
that distinguish(es) both from each other! It is tough for a newbie in this
field to get a clear image without profound experiences. Any clue will be
highly appreciated.

Frank Que

From: bob nerkul
Subject: Re: distinction?
Date: 
Message-ID: <3a296fe5.1111202@news.btinternet.com>
On Sat, 2 Dec 2000 12:58:53 -0800, "Frankque" <········@infinet.net>
wrote:

>Hi! Guru here:
>
>I know Scheme is a dialect of Lisp. But I want know exactly the point(s)
>that distinguish(es) both from each other! It is tough for a newbie in this
>field to get a clear image without profound experiences. Any clue will be
>highly appreciated.
>
>Frank Que

A comparison here:
http://www.jps.net/ajenkins/andy/lisp_and_scheme.html

nerkul
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwlmtympa2.fsf@world.std.com>
······@my-deja.com (bob nerkul) writes:

> On Sat, 2 Dec 2000 12:58:53 -0800, "Frankque" <········@infinet.net>
> wrote:
> 
> >I know Scheme is a dialect of Lisp. But I want know exactly the point(s)
> >that distinguish(es) both from each other!
> 
> A comparison here:
> http://www.jps.net/ajenkins/andy/lisp_and_scheme.html

The above-referenced paper self-identifies as a somewhat superficial overview,
and while it has some interesting material, it's not remarkably to-the-point.

Here are some things I think are key differences between Lisp and Scheme:

 (1) They have different goals. 

     Scheme values aesthetics over virtually all else.
     Common Lisp places aesthetics low on the totem pole.

     Scheme values small size-of-language and ease-of-language-implementation.
     Common Lisp assumes that it's ok for the base language to be large and
     to take a while to implement, and that it's small size-of-program
     and ease-of-program-implementation that matters.

     Scheme abhors redundancy of expression, so tends not to offer more than
     one way to do a particular thing.
     Common Lisp assumes it serves a varied community with a variety of
     programming styles and provides numerous options to allow the coresidence
     of people with varied tastes.

     Scheme doesn't focus on implementation compatibility, and has 
     historically virtually ignored "small differences" that might make 
     for porting problems.
     Common Lisp focuses a great deal on language portability, specifying
     numerous ways of detecting subtle differences between implementation
     for ported programs trying to "get a foothold".
     
 (2) They are specified differently.

     Scheme has both an English text description of its semantics and
     a formal semantics.
     CL is specified in English text only.

 (3) They have several highly visible differenes in the core language.

     Scheme has call-with-current-continuation.  Common Lisp does not.
     UNWIND-PROTECT enjoys a clear semantics in Common Lisp but is beyond
     the scope of the language in Scheme, at least partly becuase its 
     semantics would be problematic in Scheme in the presence of 
     call-with-current-continuation (and the first class continuations 
     resulting from it).

     Order of argument evaluation in Scheme is generally unspecified, 
     whereas it is specified in Common Lisp.

     Scheme function argument notations provide primitively only for 
     "required" and "rest" arguments.  There is no provision for individual
     "optional" arguments, nor for "keyword" arguments, both provided by
     Common Lisp.

     Scheme has mandatory tail call elimination.  Common Lisp does not.

     Common Lisp separates programming units by "package" and Scheme by
     "module".  Though these are often contrasted as if they attempt to 
     solve the same problem, the two are in fact orthogonal.  CL could have
     a module system, but chooses not to.  Scheme could have a package system
     but chooses not to.  Package systems separate references at the data
     level, independent of attached semantics.  For example, the program
       (eq 'x:foo 'y:foo)
     illustrates a use of symbols that are not variables in a way that 
     exploits the package system.

     Scheme is a "Lisp1" (single variable namespace); Common Lisp has 
     several namespaces, though is commonly called merely a "Lisp2" because
     of the focus on separation of function cells and value cells; in fact,
     Common Lisp also has separated namespaces for block tags and go tags.
     A consequence of the distinction in namespaces is the presence of 
     (FUNCALL f ...) and (FUNCTION f) notations in Common Lisp, which are
     not present in Scheme.  Another consequence of this is the need for a
     much more complicated macro system in Scheme, using macro hygiene to
     avoid problems that would otherwise be introduced by name clashes;
     largely these problems do not occur in Common Lisp because of the 
     combined presence of its multiple namespaces and its package system,
     so a macro hygiene system, while it would be possible in CL is not 
     in practice needed.  Some also find the Scheme macro system elegant, 
     although most admit it is less computationally powerful than the 
     Common Lisp macro system.

     A class system and condition system are well-integrated with Common
     Lisp, and are largely absent in Scheme.
    
 (4) CL has a much larger library of functions and classes as part of
     the core language than does Scheme.  The Scheme language intends
     such libraries to be optional add-ons.  Whether this is a bug or a
     feature in either case appears to be a largely religious/political
     issue rather than a technical one.
From: Frankque
Subject: Re: distinction?
Date: 
Message-ID: <3a2985bb@news.infinetgroup.com>
Thanks for prompt replies. As says all materials that you presented, Common
Lisp seems more useful in practical problem solving than does Scheme. Why do
most universities in North America choose Scheme as their introduction
course for computer science students? Of my understanding, it is the
semantic simplicity and syntactical focus on aesthetics that makes Scheme
easier to understand and a good object to grasp core concepts in
programming. The more practically useful, the less self-evident a program
language might have presented by itself because of too many trivial concerns
about  problems in the real world to shape a fine body in a pleasant way as
what laboriously happens when people keep doing fitness daily.  I used to be
a strong believer in what Albert Einstein says: the truth must be the
harmony between simplicity and righteousness. But I have been gradually
conquered by the world that is full of trivial technologies and
implementations. Am I right? I'm more than blurred at this time.

Frank Que

"Kent M Pitman" <······@world.std.com> wrote in message
····················@world.std.com...
> ······@my-deja.com (bob nerkul) writes:
>
> > On Sat, 2 Dec 2000 12:58:53 -0800, "Frankque" <········@infinet.net>
> > wrote:
> >
> > >I know Scheme is a dialect of Lisp. But I want know exactly the
point(s)
> > >that distinguish(es) both from each other!
> >
> > A comparison here:
> > http://www.jps.net/ajenkins/andy/lisp_and_scheme.html
>
> The above-referenced paper self-identifies as a somewhat superficial
overview,
> and while it has some interesting material, it's not remarkably
to-the-point.
>
> Here are some things I think are key differences between Lisp and Scheme:
>
>  (1) They have different goals.
>
>      Scheme values aesthetics over virtually all else.
>      Common Lisp places aesthetics low on the totem pole.
>
>      Scheme values small size-of-language and
ease-of-language-implementation.
>      Common Lisp assumes that it's ok for the base language to be large
and
>      to take a while to implement, and that it's small size-of-program
>      and ease-of-program-implementation that matters.
>
>      Scheme abhors redundancy of expression, so tends not to offer more
than
>      one way to do a particular thing.
>      Common Lisp assumes it serves a varied community with a variety of
>      programming styles and provides numerous options to allow the
coresidence
>      of people with varied tastes.
>
>      Scheme doesn't focus on implementation compatibility, and has
>      historically virtually ignored "small differences" that might make
>      for porting problems.
>      Common Lisp focuses a great deal on language portability, specifying
>      numerous ways of detecting subtle differences between implementation
>      for ported programs trying to "get a foothold".
>
>  (2) They are specified differently.
>
>      Scheme has both an English text description of its semantics and
>      a formal semantics.
>      CL is specified in English text only.
>
>  (3) They have several highly visible differenes in the core language.
>
>      Scheme has call-with-current-continuation.  Common Lisp does not.
>      UNWIND-PROTECT enjoys a clear semantics in Common Lisp but is beyond
>      the scope of the language in Scheme, at least partly becuase its
>      semantics would be problematic in Scheme in the presence of
>      call-with-current-continuation (and the first class continuations
>      resulting from it).
>
>      Order of argument evaluation in Scheme is generally unspecified,
>      whereas it is specified in Common Lisp.
>
>      Scheme function argument notations provide primitively only for
>      "required" and "rest" arguments.  There is no provision for
individual
>      "optional" arguments, nor for "keyword" arguments, both provided by
>      Common Lisp.
>
>      Scheme has mandatory tail call elimination.  Common Lisp does not.
>
>      Common Lisp separates programming units by "package" and Scheme by
>      "module".  Though these are often contrasted as if they attempt to
>      solve the same problem, the two are in fact orthogonal.  CL could
have
>      a module system, but chooses not to.  Scheme could have a package
system
>      but chooses not to.  Package systems separate references at the data
>      level, independent of attached semantics.  For example, the program
>        (eq 'x:foo 'y:foo)
>      illustrates a use of symbols that are not variables in a way that
>      exploits the package system.
>
>      Scheme is a "Lisp1" (single variable namespace); Common Lisp has
>      several namespaces, though is commonly called merely a "Lisp2"
because
>      of the focus on separation of function cells and value cells; in
fact,
>      Common Lisp also has separated namespaces for block tags and go tags.
>      A consequence of the distinction in namespaces is the presence of
>      (FUNCALL f ...) and (FUNCTION f) notations in Common Lisp, which are
>      not present in Scheme.  Another consequence of this is the need for a
>      much more complicated macro system in Scheme, using macro hygiene to
>      avoid problems that would otherwise be introduced by name clashes;
>      largely these problems do not occur in Common Lisp because of the
>      combined presence of its multiple namespaces and its package system,
>      so a macro hygiene system, while it would be possible in CL is not
>      in practice needed.  Some also find the Scheme macro system elegant,
>      although most admit it is less computationally powerful than the
>      Common Lisp macro system.
>
>      A class system and condition system are well-integrated with Common
>      Lisp, and are largely absent in Scheme.
>
>  (4) CL has a much larger library of functions and classes as part of
>      the core language than does Scheme.  The Scheme language intends
>      such libraries to be optional add-ons.  Whether this is a bug or a
>      feature in either case appears to be a largely religious/political
>      issue rather than a technical one.
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwpujafco0.fsf@world.std.com>
"Frankque" <········@infinet.net> writes:

> ... Why do most universities in North America choose Scheme as their
> introduction course for computer science students?

It was specifically designed with teaching in mind.  It doesn't have a
lot of odd details to explain and is especially useful if you're
teaching languages in broad brush strokes rather than at the fine
detail.  For example, if your goal is to teach "algorithms", it hardly
matters which language you use other than in terms of grace of
presentation.  If your goal is to produce commercial quality code,
what signals what error or where the branch cuts are drawn or details
like that matter a lot more.

I know in particular at MIT when I was there (which is now 20 years ago),
there was an explicit goal of NOT teaching any programming language but
merely assuming you knew them or could learn them as needed.  The idea
was, again, to teach concepts not details.  I think the design of Scheme
and Structure and Interpetation of Computer Programs (S&ICP, the common
teaching text) reflect this.

Note well that some implementations of Scheme are as detailed and
commercial oriented as CL.  However, I would personally say that this
is due more to the individual commitment of the implementor than the
language; I would almost go so far as to say these implementations
succeed in spite of the basic spartan design of Scheme, rather than
due to it.  Of course, the Scheme designers will claim that it follows
from their spartan design that such good implementations arise, but I
doubt that is really true.  Nothing about the Scheme spec especially
suports a vendor in the creation of an efficient implementation.  And,
if I remember right, Steele at some point early on wrote a compiler
for Scheme called "Cheapy", which turned out to produce code that ran
slower compiled than interpreted... something that we might naively
think of as "not possible" until we think about it, but that is in 
fact not a property of the universe, so much as a property of which
product results people are willing to actually show their friends...

> Of my understanding, it is the
> semantic simplicity and syntactical focus on aesthetics that makes Scheme
> easier to understand and a good object to grasp core concepts in
> programming.

Yes.  And fortunately or unfortunately, really depending on how you look at
it, these concepts it teaches you don't really map neatly onto what you can
get in any other language.  It stretches your thinking in interesting ways,
and then the question of whether you can apply that usefully later is an open
one.  But then Lisp has some of that same character, just in different places.
So I won't say that's an automatic negative.  Just something to ponder.

> The more practically useful, the less self-evident a program
> language might have presented by itself because of too many trivial concerns
> about  problems in the real world to shape a fine body in a pleasant way as
> what laboriously happens when people keep doing fitness daily.

Hmm.  I didn't quite resonate with that analogy, but I will say that it's
really a personal preference issue what is aesthetic.  The Scheme people
often speak as if it's self-obvious that the smallest language is the
most elegant, but I don't think that's really true.  I think each language
is like a set of axioms, arbitrarily chosen, and that the programs are like
proofs--their nature follows from the axioms in search of a given goal.

I don't mind that people teach people the relation between recursion and
iteration, but I do mind a LOT that they try to untrain them to think in
terms of standard iteration constructs and to think such things are dirty
in some way that tail recursion is blessed not to be.  College courses should
teach "alternatives", not "dogma".  And the Scheme community is, for whatever
reason, rich with dogma.

> I used to be
> a strong believer in what Albert Einstein says: the truth must be the
> harmony between simplicity and righteousness. But I have been gradually
> conquered by the world that is full of trivial technologies and
> implementations. Am I right? I'm more than blurred at this time.

I go with Aristotle and virtue ethics.  That the virtues are the mid-points
between extremes.  In other terms, he was saying that if you just take a
given design axis with negative infinity on one end and infinity on the other
end, you just need to find the midpoint between those two infinities to be
happy.  The funny thing about infinities is that the midpoint doesn't have
to be zero, and it's more the search for the midpoint than the fact of the
midponit that is itself noble.  Put another way, at the point where you stop
seeking new ways to look at things and new values and ideas to accomodate,
thinking you have the answer, it's at that point that you probably are
starting to finally lose.  

One of the things I like about CL's rough edges is how it accomodates
multiple points of view without breaking the mold.  There are some
standard analogies which I'll misquote and someone will correct me on
about APL being like a diamond--if you try to change it, it will
shatter.  Was it Perlis who said this? Lisp has been called (by Joel
Moses?) a ball of mud--you can stick more mud to it and it will still
be a ball of mud.  There's some virtue in that, I think.  Where you think
Scheme sits in that space I suppose is open to interpretation...
From: David McClain
Subject: Re: distinction?
Date: 
Message-ID: <t2jr132luknoc1@corp.supernews.com>
Kent M Pitman wrote in message ...
>I don't mind that people teach people the relation between recursion and
>iteration, but I do mind a LOT that they try to untrain them to think in
>terms of standard iteration constructs and to think such things are dirty
>in some way that tail recursion is blessed not to be.  College courses
should
>teach "alternatives", not "dogma".  And the Scheme community is, for
whatever
>reason, rich with dogma.
>


Kent, I am intruiged by your comment here. Don't you find that many of the
conventional iteration techniques force the user to invent internal state
variables that detract from the simplicity of what is being computed? I am
coming at this question from the standpoint of the ML languages in which
data are largely immutable, tail recursion is optimized and explicitly
encouraged over iteration. OCaml allows conventional iteration but does not
encourage its use.

- DM
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfw1yvpsfo6.fsf@world.std.com>
"David McClain" <········@azstarnet.com> writes:

> Kent M Pitman wrote in message ...
> >I don't mind that people teach people the relation between recursion and
> >iteration, but I do mind a LOT that they try to untrain them to think in
> >terms of standard iteration constructs and to think such things are dirty
> >in some way that tail recursion is blessed not to be.  College courses
> should
> >teach "alternatives", not "dogma".  And the Scheme community is, for
> whatever
> >reason, rich with dogma.
> 
> Kent, I am intruiged by your comment here. Don't you find that many of the
> conventional iteration techniques force the user to invent internal state
> variables that detract from the simplicity of what is being computed? 

Certainly it's true that sometimes they force the creation of extra
syntax but my point is that linguistically, people already do that
before they come to any computer language.  Even non-programmers know
what it means to say "For every setting at the table, make sure the
napkin is arranged right".  People are not taught "To set the table
for some number of settings, first check if you are done and if not
then check the first napkin is arranged right and then set the table
for the rest of the settings."  There are situations where recursion
is good, and adds a lot.  It should be in everyone's repertoire.  But
there are places where it's just unnatural, in that it does not mirror
the way people talk.

> I am coming at this question from the standpoint of the ML languages
> in which data are largely immutable, tail recursion is optimized and
> explicitly encouraged over iteration.

The issue should just be syntactic.  There should be no semantic issue
here, and hence no speed issue.

> OCaml allows conventional iteration but does not encourage its use.

CL allows implementations to allow tail recursion, but does not require
it work nor encourage its use.

In one way, it saddens me that CL doesn't require the optimization because
I'd really like people to be able to use it when they can.

But on the other hand, I regard it almost as "remedial Scheme", snapping
people out of barouque notations they have learned in Scheme class and
forcing them to realize there are other ways of saying the same thing.
Had they been taught the fact of "choice" in Scheme class, I'd gladly 
allow them that choice.  But since they were taught dogma, it just pisses
me off that they walk into a CL shop with a deathwish for perfectly 
perspicuous iteration constructs like dotimes and dolist, and even for
some forms of loop (which I defend these days to a limited degree, though 
I recognize can sometimes get syntactically out of hand; for years I 
railed against LOOP because its syntax is idiosyncratic and it is sometimes
opaque to debugging, but ultimately I could not argue with its abillity
to capture and combine many useful idioms that were not made perspicuous in
other syntaxes.)
From: David McClain
Subject: Re: distinction?
Date: 
Message-ID: <t2mbf9ht024hed@corp.supernews.com>
Kent M Pitman wrote in message ...
>allow them that choice.  But since they were taught dogma, it just pisses
>me off that they walk into a CL shop with a deathwish for perfectly
>perspicuous iteration constructs like dotimes and dolist, and even for
>some forms of loop (which I defend these days to a limited degree, though


Yes, I had forgotten about dolist and dotimes. I use these all the time, and
they don't explicitly pepper the code with intermediate state variables. In
this sense of iterative construct, I can definitely agree with their use as
more direct and less opaque than accumulating tail recursive routines.

- DM
From: David McClain
Subject: Re: distinction?
Date: 
Message-ID: <t2mce0c2rg1b0c@corp.supernews.com>
I work mostly with the code of other physicists and engineers... I wish more
were taught in early programming courses about recursion, simply because the
code I run into most that is absolutely nighmarish, is that where control
vars are peppered throughout the code, and these are globals. In typical
Fortran style, even Lisp produced by these folks has the same nightmarish
quality. I would venture to say that most of the industrial and scientific
community uses these poor practices and this is what accounts for their
abysmal records with cost and schedule overruns on software projects.

I recently had the dubious pleasure of editing another scientist's Lisp code
and porting it to a more modern dialect of Lisp. His penchant for using
globals containing local state information makes it almost impossible to
reproduce simply because it is difficult to track which functions step on
these shared variables across the two-dozen or so modules of Lisp. Yechh!

Please, let's stop teaching Fortran as a first and only language, and start
passing along a little more abstract reasoning, like functional closures,
recursion, immutable global data, and so forth. Most scientists feel that
they don't need to learn anything more about programming than what they
learned as college freshmen. I find that a lot of Pysiciains and Attorneys
also think this way. Hey, after all they got their Doctorates in whatever,
what more is there worth learning?

- DM
From: Erik Naggum
Subject: Re: distinction?
Date: 
Message-ID: <3184932062637126@naggum.net>
* "David McClain" <········@azstarnet.com>
| I recently had the dubious pleasure of editing another scientist's
| Lisp code and porting it to a more modern dialect of Lisp.  His
| penchant for using globals containing local state information makes it
| almost impossible to reproduce simply because it is difficult to track
| which functions step on these shared variables across the two-dozen or
| so modules of Lisp.  Yechh!

  Some Common Lisp environments come with a cross referencing facility
  that allows you to query the system for all such references, such as
  Allegro CL from Franz Inc.  It doesn't take the pain of dealing with
  such code away, but you can at least retain control over it.

#:Erik
-- 
  "When you are having a bad day and it seems like everybody is trying
   to piss you off, remember that it takes 42 muscles to produce a
   frown, but only 4 muscles to work the trigger of a good sniper rifle."
								-- Unknown
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwk89gsjti.fsf@world.std.com>
"David McClain" <········@azstarnet.com> writes:

> I work mostly with the code of other physicists and engineers... I wish more
> were taught in early programming courses about recursion, simply because the
> code I run into most that is absolutely nighmarish

I guess my point is that some things "feel" recursive and should be expressed
recursively.  But some things "feel" iterative, and I don't see anything wrong
with:

 (loop for entry in some-list
       for name = (person-name entry)
       for age  = (person-age  entry)
       collect (list name age))

You can express this and many other things in terms of tail recursion, 
but I don't personally see the value of doing so.  Even so, my point is that
students should be taught that this kind of breakdown is just as acceptable
as tail recursion.  I do so tire of having to de-program Scheme converts
from believing that only the Scheme-style

  (let loop ((input list) (output '()))
    (if (null? input) (reverse! output)
        (let ((entry (first input)))
          (let ((name (person-name entry))
		(age  (person-age  entry)))
            (loop (cdr input) (cons (list name age) output))))))

is acceptably clear.  Among other things, this contains a lot of verbiage
which is subprimitive to what's being accomplished, such as the need
to maintain an extra loop variable for the list being traversed, and another
for the result being accumulated, not to mention the programmer having to
know the stupid trick about consing up a list backward and then reversing it,
which though good "world knowledge" for a programmer to have really isn't 
relevant to the domain task at hand.  And, of course, Common Lisp doesn't
have tail recursion elimination, so to avoid possible stack overflow in the
case of long lists, the Scheme loop above would have to at least be rewritten
using DO (which is effectively a sugaring of a tail recursive loop). But
LOOP hides these "implementation level" extra variables, the knowledge of
accumulation tricks, and certain potential "stack" issues and other traversal
strategy issues in a way that I have over time come to agree with LOOP
proponents is expressionally important.

So in a sense, I think Lisp is closer than Scheme to your stated goal
of avoiding places where "where control vars are peppered throughout
the code".
From: ········@hex.net
Subject: Re: distinction?
Date: 
Message-ID: <wkelzo5c1v.fsf@441715.i-did-not-set--mail-host-address--so-shoot-me>
>>>>> "Kent" == Kent M Pitman <······@world.std.com> writes:
Kent> "David McClain" <········@azstarnet.com> writes:
>> I work mostly with the code of other physicists and
>> engineers... I wish more were taught in early programming
>> courses about recursion, simply because the code I run into
>> most that is absolutely nighmarish

Kent> I guess my point is that some things "feel" recursive and should
Kent> be expressed recursively.  But some things "feel" iterative, and
Kent> I don't see anything wrong with:

Kent>  (loop for entry in some-list 
Kent>        for name = (person-name entry)
Kent>        for age = (person-age entry) 
Kent>      collect (list name age))

Kent> You can express this and many other things in terms of tail
Kent> recursion, but I don't personally see the value of doing so.
Kent> Even so, my point is that students should be taught that this
Kent> kind of breakdown is just as acceptable as tail recursion.  I do
Kent> so tire of having to de-program Scheme converts from believing
Kent> that only the Scheme-style

; (let loop
;     ((input list) 
;      (output '())) 
;   (if (null? input) 
;       (reverse! output)
;       (let ((entry (first input))) 
; 	(let ((name  (person-name entry)) 
; 	      (age (person-age entry)))
; 	  (loop (cdr input) 
; 		(cons (list name age) output))))))

Kent> is acceptably clear.

Kent> Among other things, this contains a lot of verbiage which is
Kent> subprimitive to what's being accomplished, such as the need to
Kent> maintain an extra loop variable for the list being traversed,
Kent> and another for the result being accumulated, not to mention the
Kent> programmer having to know the stupid trick about consing up a
Kent> list backward and then reversing it, which though good "world
Kent> knowledge" for a programmer to have really isn't relevant to the
Kent> domain task at hand.  And, of course, Common Lisp doesn't have
Kent> tail recursion elimination, so to avoid possible stack overflow
Kent> in the case of long lists, the Scheme loop above would have to
Kent> at least be rewritten using DO (which is effectively a sugaring
Kent> of a tail recursive loop). But LOOP hides these "implementation
Kent> level" extra variables, the knowledge of accumulation tricks,
Kent> and certain potential "stack" issues and other traversal
Kent> strategy issues in a way that I have over time come to agree
Kent> with LOOP proponents is expressionally important.

Kent> So in a sense, I think Lisp is closer than Scheme to your stated
Kent> goal of avoiding places where "where control vars are peppered
Kent> throughout the code".

I certainly agree with you that the "feel" of the LOOP-based version
of this is _vastly_ nicer than the "hand-coded tail recursion."

I would suggest the thought that the popularity of the latter falls
out of three considerations:

a) Scheme is presented as an academic language, and the quality of
   teaching will not be uniformly wonderful.

   It is *certainly* going to be used as a tool for teaching
   recursion; a _good_ course might move on to present iteration, but
   would do so as a secondary matter.  "Questionable" courses may
   never get around to indicating that you can represent structures in
   an iterative way.  Only an *excellent* course would promote the
   equality of iteration and recursion.

b) Presentation of _both_ iteration and recursion and the "software
   engineering" side requires more time than may get devoted to
   Scheme.

   In a brief two week module on "Lisp," it's hard to get past the
   prejudices of Lisp being basically about recursion and lists.

   Moving on to a _truly_ fuller view takes further time.

c) Macros aren't crucial to Scheme the same way they are to Common
   Lisp.

   This too is related to a) and b); a shallow examination of "Lisp,"
   in _whatever_ form, won't get around to the relatively advanced
   topic of macros.

   Schemely support for macros is not uniform, and there
   are a couple of competing macro systems.  On the one hand, this
   does not encourage their use.  On the other hand, it does not
   encourage usage of facilities that _require_ their use.  [LOOP
   being the "pathological" example of this...]

   In contrast, CL implements a considerable chunk of the language via
   macros, and the notion of the language being extensible comes from
   this.

   It's only the most ambitious of academic presentations that would
   get into macros in either Lisp variation; the lack of extensive
   extensions in Scheme that use macros have the result that there's a
   fair bit of "starting from scratch" that would result.
-- 
(concatenate 'string "cbbrowne" ·@hex.net")
<http://www.ntlug.org/~cbbrowne/macros.html>
All ITS machines now have hardware for a new machine instruction --
XOI Execute Operator Immediate.
Please update your programs.
From: Dorai Sitaram
Subject: Re: distinction?
Date: 
Message-ID: <90gtse$gg0$1@news.gte.com>
In article <···············@world.std.com>,
Kent M Pitman  <······@world.std.com> wrote:
>
>Among other things, this contains a lot of verbiage
>which is subprimitive to what's being accomplished, such as the need
>to maintain an extra loop variable for the list being traversed, and another
>for the result being accumulated, not to mention the programmer having to
>know the stupid trick about consing up a list backward and then reversing it,
>which though good "world knowledge" for a programmer to have really isn't 
>relevant to the domain task at hand.  

There is a quite antient technique that allows one to
build up a list left-to-right in one pass, at the
constant overhead of just a couple of extra conses.
Nobody seems to use it though and it isn't even
mentioned in textbooks anymore.  I think I saw it in an
old book by Wilensky or Touretzky?

--d 
From: Tim Bradshaw
Subject: Re: distinction?
Date: 
Message-ID: <nkjelzoszhw.fsf@tfeb.org>
····@goldshoe.gte.com (Dorai Sitaram) writes:

> 
> There is a quite antient technique that allows one to
> build up a list left-to-right in one pass, at the
> constant overhead of just a couple of extra conses.
> Nobody seems to use it though and it isn't even
> mentioned in textbooks anymore.  I think I saw it in an
> old book by Wilensky or Touretzky?

I think it's used a lot -- either by things like

   (loop for ...
      collect ..)

or wrapped in a macro such as my COLLECING / WITH-COLLECTORS things
(http://www.tfeb.org/lisp/hax.html#COLLECTING) which are probably
pretty typical of what people do.

--tim

	
From: Erik Naggum
Subject: Re: distinction?
Date: 
Message-ID: <3184959294361655@naggum.net>
* Dorai Sitaram
| There is a quite antient technique that allows one to
| build up a list left-to-right in one pass, at the
| constant overhead of just a couple of extra conses.

  Only one extra cons, actually.

(do* ((tail (cons nil nil) (cdr tail))
      (head (cdr tail))
      (list <list> (cdr list))
      element)
    ((null list) head)
  (setf element (car list))
  ...
  (setf (cdr tail) (list element)))

| Nobody seems to use it though and it isn't even mentioned in textbooks
| anymore.

  Well, it has naturally become macrofied because it _is_ quite hairy
  and intrusive to write manually every time.  Software patterns
  notwithstanding, some things are just better off being macros.

| I think I saw it in an old book by Wilensky or Touretzky?

  I have only seen it explained.  The coding seems to vary according to
  the specific needs of the body of the loop.

#:Erik
-- 
  "When you are having a bad day and it seems like everybody is trying
   to piss you off, remember that it takes 42 muscles to produce a
   frown, but only 4 muscles to work the trigger of a good sniper rifle."
								-- Unknown
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwsno3hguk.fsf@world.std.com>
Erik Naggum <····@naggum.net> writes:

> | Nobody seems to use it though and it isn't even mentioned in textbooks
> | anymore.
> 
>   Well, it has naturally become macrofied because it _is_ quite hairy
>   and intrusive to write manually every time.  Software patterns
>   notwithstanding, some things are just better off being macros.

Plus it conses junk.  In every implementation I know of, included
cdr-coded implementations, the NREVERSE trick makes permanent use
of every cons cell you make along the way.  I don't like throwing
away that extra cons cell.

Btw, didn't Interlisp have some operator that encapsulated this better
linguistically?  I never programmed in Interlisp, but vaguely recall
something called TCONC or something ("tail conc") which I think required
some kind of setup in order to be used.  No manual here so can't check.

> | I think I saw it in an old book by Wilensky or Touretzky?
> 
>   I have only seen it explained.  The coding seems to vary according to
>   the specific needs of the body of the loop.

Yes.  Another reason it's hard to use.
From: Carl Shapiro
Subject: Re: distinction?
Date: 
Message-ID: <ouybsur5ze6.fsf@panix3.panix.com>
Kent M Pitman <······@world.std.com> writes:

> Btw, didn't Interlisp have some operator that encapsulated this better
> linguistically?  I never programmed in Interlisp, but vaguely recall
> something called TCONC or something ("tail conc") which I think required
> some kind of setup in order to be used.  No manual here so can't check.

Interlisp had two such functions.  There was TCONC which would listify
and NCONC an item to the end of a TCONC structure, and LCONC which
would NCONC lists to the end of a TCONC structure.  Calling TCONC (and
IIRC, LCONC) with no arguments would initialize a the structure.
From: Janis Dzerins
Subject: Re: distinction?
Date: 
Message-ID: <87k89fuv6a.fsf@asaka.latnet.lv>
····@goldshoe.gte.com (Dorai Sitaram) writes:

> There is a quite antient technique that allows one to
> build up a list left-to-right in one pass, at the
> constant overhead of just a couple of extra conses.

It seems like a queue to me.

> Nobody seems to use it though and it isn't even
> mentioned in textbooks anymore.

I suppose many use queues (at least I do).

> I think I saw it in an old book by Wilensky or Touretzky?

An implementation of queues with one extra cons is in the PAIP, page
341.

Janis Dzerins
-- 
  If million people say a stupid thing it's still a stupid thing.
From: Paolo Amoroso
Subject: Re: distinction?
Date: 
Message-ID: <rAMsOvA0Hn9wM6cqrK4JqtJD7vuB@4ax.com>
On 4 Dec 2000 20:13:02 GMT, ····@goldshoe.gte.com (Dorai Sitaram) wrote:

> There is a quite antient technique that allows one to
> build up a list left-to-right in one pass, at the
> constant overhead of just a couple of extra conses.

Can you please outline it?


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: Paolo Amoroso
Subject: Re: distinction?
Date: 
Message-ID: <qCUtOoiNw5ZhqID0RORdNtQ1Z3g5@4ax.com>
On Tue, 05 Dec 2000 13:38:45 +0100, Paolo Amoroso <·······@mclink.it>
wrote:

> Can you please outline it?

Never mind, I have just seen Erik's code. Thanks anyway,


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: Erik Naggum
Subject: Re: distinction?
Date: 
Message-ID: <3185040299547567@naggum.net>
* Paolo Amoroso <·······@mclink.it>
| Never mind, I have just seen Erik's code. Thanks anyway,

  Hm.  My code is slightly different from the algorithm that Dorai
  described.  His implementation would use a cons cell to hold both the
  head and the tail, instead of using two variables, and is thus
  slightly more complex, and would indeed use two extra cons cells, but
  it could also return it as a single object.  That has some value, but
  it would at that point better be described as a queue, not just a
  simple list-creating software pattern, but this may just be one of
  those reasons why software patterns are sometimes useful: It is too
  hard to make this a general idea except in those cases where it is
  naturally made into a macro as far as you can type it.

#:Erik
-- 
  "When you are having a bad day and it seems like everybody is trying
   to piss you off, remember that it takes 42 muscles to produce a
   frown, but only 4 muscles to work the trigger of a good sniper rifle."
								-- Unknown
From: Dorai Sitaram
Subject: Re: distinction?
Date: 
Message-ID: <90ir63$hr1$1@news.gte.com>
In article <····························@4ax.com>,
Paolo Amoroso  <·······@mclink.it> wrote:
>On 4 Dec 2000 20:13:02 GMT, ····@goldshoe.gte.com (Dorai Sitaram) wrote:
>
>> There is a quite antient technique that allows one to
>> build up a list left-to-right in one pass, at the
>> constant overhead of just a couple of extra conses.
>
>Can you please outline it?

I think you may have already gotten the gist from
the ensuing posts.  The actual list L is held in the
car of an extraneous cons cell C, whose cdr contains
the last cdr of L.  This allows you to add a new
element to the end of L in constant time.  Of course
when you do so you must also ensure that C's cdr
continues to point to the (new) last cdr of L, which
also takes constant time.

As Janis Dzerins said, it is like a queue.  So you
could punningly refer to L, the list proper
inside C, as the "list in q(uestion)".

--d
From: Jon Jacky
Subject: Re: distinction?
Date: 
Message-ID: <u9ofyrn31d.fsf@bilbo.radonc.washington.edu>
Kent M Pitman <······@world.std.com> writes:

> Even non-programmers know
> what it means to say "For every setting at the table, make sure the
> napkin is arranged right".  

This can be expressed functionally in Scheme using map (like mapcar in CL).
It's not necessary to use iteration.

Harvey and Wright's textbook Simply Scheme makes this point.
They introduce higher-order functions before recursion.

-- 

Jonathan Jacky				···@radonc.washington.edu
Radiation Oncology, Box 356043		voice:	(206)-598-4117
University of Washington		FAX:	(206)-598-6218	
Seattle, Washington  98195-6043	USA

http://www.radonc.washington.edu/prostaff/jon/
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwwvdfd5x2.fsf@world.std.com>
Jon Jacky <···@bilbo.radonc.washington.edu> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > Even non-programmers know
> > what it means to say "For every setting at the table, make sure the
> > napkin is arranged right".  
> 
> This can be expressed functionally in Scheme using map (like mapcar in CL).
> It's not necessary to use iteration.

But MAP is not good for expressing "For every number from 0 to 9, make sure
it appears on the phone dial" because Scheme does not provide an object
over which one can "map" numeric ranges, as CL's LOOP does.  Neither does
Scheme provide the ability to map over objects like hash tables.  Nor does
map provide the ability to accumulate results flexibly as truth values,
sums, etc.  Nor does Scheme provide the ability to step through only
every second or third value in a list, as CL's LOOP does.  Yes, recursion
gets you this, but you must "implement" rahter than "express" this.
That is, the language you write uses subprimitive terms whose net effect
is to cause a certain behavior, not direct terminology that is known to 
capture exceedingly well-known and well-established idioms.

Indeed, the Scheme community has outright shunned the creation of standard
terminology in the language, preferring that it be added elsewhere.  In so
doing, and in not creating itself a useful library that is part of the
standard, it must stand the criticism that comes from not including this
stuff, just as we must stand the criticism that they levy for our having
included it.

I think one of the greatest strengths of CL is not that it makes in any way
the best decision of how to standardize certain facilities, since there can
be no uniquely determined best (and this is why Scheme is forever at an 
impassible barrier, waiting for consensus on the "right" way to do things,
when no right way can ever exist), but rather the strength of CL is that 
it has the guts to recognize the need for arbitrary choices as a way of forging
forward.  It's the willingness to suffer the slings and arrows that come
from having to defend what cannot be defended that allows programmers on a 
dailiy basis to consider numerous issues settled in CL, while those same
issues continue to occupy many Scheme programmers' time just because the
language wouldn't take a stand.

Often, I think, it's more important to have something that's standard than
something that's wrong.  (Well, you don't want it to be completely broken,
of course, but among several possible choices with positives and negatives
for each, you can tolerate quite a lot of negatives if the outcome is
standardization on top of which other stuff can be built.)  CL isn't the
only language to notice this--Java is a living monument to this design
strategy.

> Harvey and Wright's textbook Simply Scheme makes this point.
> They introduce higher-order functions before recursion.

The teaching of the language often comes, as in the case of Simply Scheme,
with a lot of extra stuff that is not part of the language.  People beat
up on Lisp for having a lot of extra stuff IN the language, but that means
at least that the whole community has the same starting point and doesn't
need to quibble over how to express common idioms that everyone has.

It's certainly possible to write particular named programs that employ
recursion and are still possible to understand as "expression".  But the
mere fact of the use of recursion and higher-order functions does not
force this.  For example,

  (mymap f lst cddr)

might be a way to specify how to step over every other element of lst when
mapping f over it, but it's not perspicuous.  For all the possible elements
of a mapping operation (the step, the accumulation, etc.) that I could
want to affect, I need functional entry points for each one and the language
helps me not at all with this--there aren't even optional args, much less
keyword args.  So it's maybe "concise" but it's far from "expressive" in
the sense that I mean it, which is specifically "focusing on terminology
that expresses rather than implements an idea".  That doesn't mean 
syntactically minimal.  For example, if you could say 

 (mymap  f lst step: cddr)

that would be an improvement in the domain of language expressivity.
From: Joe Marshall
Subject: Re: distinction?
Date: 
Message-ID: <hf4jvctb.fsf@content-integrity.com>
Kent M Pitman <······@world.std.com> writes:

> Indeed, the Scheme community has outright shunned the creation of standard
> terminology in the language, preferring that it be added elsewhere.  In so
> doing, and in not creating itself a useful library that is part of the
> standard, it must stand the criticism that comes from not including this
> stuff, just as we must stand the criticism that they levy for our having
> included it.

That is a valid criticism.  But most of the `industrial' Scheme
implementations (like MIT Scheme, T, or MzScheme) provided a much
richer set of tools.  They didn't think such tools should be part of
the language spec for Scheme in general.

> I think one of the greatest strengths of CL is not that it makes in any way
> the best decision of how to standardize certain facilities, since there can
> be no uniquely determined best (and this is why Scheme is forever at an 
> impassible barrier, waiting for consensus on the "right" way to do things,
> when no right way can ever exist), but rather the strength of CL is that 
> it has the guts to recognize the need for arbitrary choices as a way of forging
> forward.  It's the willingness to suffer the slings and arrows that come
> from having to defend what cannot be defended that allows programmers on a 
> dailiy basis to consider numerous issues settled in CL, while those same
> issues continue to occupy many Scheme programmers' time just because the
> language wouldn't take a stand.

Scheme is mostly a `research' and `teaching' language.  It isn't so
much that Scheme people are afraid of taking a stand, or can't come to
a consensus, but more that by excising minutae from the language,
it becomes easier to reason about it, redesign it, and experiment.

These are not the goals of Common Lisp.


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwhf4jwf96.fsf@world.std.com>
Joe Marshall <···@content-integrity.com> writes:

> Scheme is mostly a `research' and `teaching' language.  It isn't so
> much that Scheme people are afraid of taking a stand, or can't come to
> a consensus, but more that by excising minutae from the language,
> it becomes easier to reason about it, redesign it, and experiment.

I'm one of the Scheme report authors.  No single individual can speak for
the bunch, of course, so it's just my opinion--but I've been there in the
meetings (thought there have been none recently) and I've read the e-mail.
We delayed I think literally years in putting in 
  (define (foo x) x)
as a required syntax of the language because some people were't sure it
was really needed over
  (define foo (lambda (x) x))
even though it was extraordinarily common in implementations. I don't think
I'm going out on a limb by saying that the group was, at least collectively,
afraid to do the arbitrary.  The problem wasn't merely conservatism, but was
also that there was simply no voting procedure until very close to the end,
and even now it's not exploited, and so everything had to be done by unanimity.
And when one has a room full of people with differing opinions, that means
really nothing gets done.  Appealing to the lowest common denominator is not
the same as a conservative design style.  Most people in the room had 
conservative design styles, any one of which went well beyond what we had.
The hard part wasn't being conservative, it was agreeing on which conservative
style to go with.  And that meant taking an even-more-than-merely-conservative
position.

That, at least, is my recollection of how things were.  I'm sure others there
would describe it differently, although I can't guess how.

As to its being mostly a research and teaching language, I know there
were people in the room that were passionate that it should grow
beyond that.  It's just that they were not able to get consensus
because of the unanimity rule.  (I was probably in the extreme end of
wanting it to be "usable", though there with me were several vendors
who were tired of the "academic" angle and wanted the language to
shine commercially. I definitely remember discussions about how if it
ever became usable, it would be the death of the language because then
lots of people who were users would want control of it and the
committee would lose its control.)
From: Frankque
Subject: Re: distinction?
Date: 
Message-ID: <3a2d33a8@news.infinetgroup.com>
It seems to go to a similar dispute to that over Apples and PCs. Fetishism
has been  the dominant in some countries, even "super country". Which have
conceived many paradox embryoes and continues to give them birth to the real
world. Offering effective solutions is all about what the science and
technology are in nature. But to what ultimation the solution should serve
any demands keeps stray. I would see some of demands should never be fed by
scientific and technological resorts. We are creating the future image of
the world by daily outcomes of our trivial work. Who would really pay
attention to  that what we are doing today will be the basis of tomorrow,
that how durable today's basis is going to last in order for tomorrow's
skyscrapers not to corrupt down? I guess few is concerned to with those
questions because human beings intelligence has not been developed so high
that they are able to realize exactly what will happen in the even very near
future in terms of the censure of current occurrence that human beings is
supposed to take the responsibility for. I realize soberly that this is not
a political or social movement forum. However, I believe that when things,
no matter "pure scientific or academic",  come to involving in human
existence, everything we are doing counts significantly. Fast growing
demands lead to outrageous spending our limited sources in the earth. We
should calm down a bit and think about a small, fine restructured world
instead of a unhurdled competition on greedily seizing what we are not
supposed to possess today from our offspring's.

Jeff
"Kent M Pitman" <······@world.std.com> wrote in message
····················@world.std.com...
> Joe Marshall <···@content-integrity.com> writes:
>
> > Scheme is mostly a `research' and `teaching' language.  It isn't so
> > much that Scheme people are afraid of taking a stand, or can't come to
> > a consensus, but more that by excising minutae from the language,
> > it becomes easier to reason about it, redesign it, and experiment.
>
> I'm one of the Scheme report authors.  No single individual can speak for
> the bunch, of course, so it's just my opinion--but I've been there in the
> meetings (thought there have been none recently) and I've read the e-mail.
> We delayed I think literally years in putting in
>   (define (foo x) x)
> as a required syntax of the language because some people were't sure it
> was really needed over
>   (define foo (lambda (x) x))
> even though it was extraordinarily common in implementations. I don't
think
> I'm going out on a limb by saying that the group was, at least
collectively,
> afraid to do the arbitrary.  The problem wasn't merely conservatism, but
was
> also that there was simply no voting procedure until very close to the
end,
> and even now it's not exploited, and so everything had to be done by
unanimity.
> And when one has a room full of people with differing opinions, that means
> really nothing gets done.  Appealing to the lowest common denominator is
not
> the same as a conservative design style.  Most people in the room had
> conservative design styles, any one of which went well beyond what we had.
> The hard part wasn't being conservative, it was agreeing on which
conservative
> style to go with.  And that meant taking an
even-more-than-merely-conservative
> position.
>
> That, at least, is my recollection of how things were.  I'm sure others
there
> would describe it differently, although I can't guess how.
>
> As to its being mostly a research and teaching language, I know there
> were people in the room that were passionate that it should grow
> beyond that.  It's just that they were not able to get consensus
> because of the unanimity rule.  (I was probably in the extreme end of
> wanting it to be "usable", though there with me were several vendors
> who were tired of the "academic" angle and wanted the language to
> shine commercially. I definitely remember discussions about how if it
> ever became usable, it would be the death of the language because then
> lots of people who were users would want control of it and the
> committee would lose its control.)
From: Rob Warnock
Subject: Re: distinction?
Date: 
Message-ID: <90i9te$6uger$1@fido.engr.sgi.com>
Kent M Pitman  <······@world.std.com> wrote:
+---------------
| Jon Jacky <···@bilbo.radonc.washington.edu> writes:
| > This can be expressed functionally in Scheme using map...
| > It's not necessary to use iteration.
| 
| But MAP is not good for expressing "For every number from 0 to 9, make sure
| it appears on the phone dial" because Scheme does not provide an object
| over which one can "map" numeric ranges, as CL's LOOP does.
+---------------

I tend to use the functions "iota" and "every" for that kind of thing:

    (unless (every (map (lambda (x) (is-on-dial? phone x) (iota 10))))
      ... )

And in Scheme, one tends to use closures a lot more, so "is-on-dial?"
would probably already be closed over the "phone" object:

    (let (is-on-dial? (lambda (x) (phone x)))
      ...
      (unless (every (map is-on-dial? (iota 10)))
        ... ))

+---------------
| Neither does Scheme provide the ability to map over objects like
| hash tables.
+---------------

Since hash tables aren't in the Scheme spec, "Scheme" doesn't provide
mapping over them either. But those implementations which *do* provide
a hash table extension also always (AFAIK) provide an enumeration method,
e.g., MzScheme provides "hash-table-map" & "hash-table-for-each":

	> (let* ((h (make-hash-table))
	         (put! (lambda (x) (hash-table-put! h (car x) (cadr x)))))
	    (for-each put! '((foo 13) (bar 7) (baz 23) (gorp 42)))
	    (hash-table-remove! h 'baz)
	    (hash-table-for-each h (lambda (k v)(print k " ==> " v) )))
	foo ==> 13
	bar ==> 7
	gorp ==> 42
	> 

But I'll grant Scheme implementations don't tend to provide mapping or
iteration over other sequence types such as vector or string (although
there's a SRFI for that).

+---------------
| Indeed, the Scheme community has outright shunned the creation of standard
| terminology in the language, preferring that it be added elsewhere.  In so
| doing, and in not creating itself a useful library that is part of the
| standard, it must stand the criticism that comes from not including this
| stuff...
+---------------

True enough, though the SRFI process <URL:http://srfi.schemers.org> seeks
to partially remedy that by providing an extra-standard concensus on many
of those issues.

+---------------
| I think one of the greatest strengths of CL is not that it makes in any way
| the best decision of how to standardize certain facilities, since there can
| be no uniquely determined best (and this is why Scheme is forever at an 
| impassible barrier, waiting for consensus on the "right" way to do things,
| when no right way can ever exist)
+---------------

Again, the SRFI process is heading away from "the one true way", more
towards a quasi-experimental process of "here's a useful way, can we
all agree it's useful to some large-enough subset of us?"

+---------------
| the strength of CL is that it has the guts to recognize the need for
| arbitrary choices as a way of forging forward.
+---------------

I'll stop with SRFI mantra after one more mention here, but I do think
that maybe the SRFIs *are* to a large extent an attempt to do exactly
that -- forge forward with a few fairly-carefully thought-out but
essentially still arbitrary choices, recruit some implementations,
let people *use* then, and see what happens.

+---------------
|   (mymap f lst cddr)
| 
| might be a way to specify how to step over every other element of lst when
| mapping f over it, but it's not perspicuous.  For all the possible elements
| of a mapping operation (the step, the accumulation, etc.) that I could
| want to affect, I need functional entry points for each one and the language
| helps me not at all with this--there aren't even optional args, much less
| keyword args.
+---------------

"In the language", meaning IEEE or R5RS Scheme, no. You're right there.
But many of use routinely allow ourselves the *usefulness* of optionals
and keywords, by using helper routines to parse the "rest" argument
(improper lambda list) that Scheme-the-language does provide. E.g.,
my personal "iota" allows "end", "start/end", or "start/step/end":

	> (iota)
	procedure iota: expects at least 1 argument, given 0
	> (iota 5)
	(0 1 2 3 4)
	> (iota 5 10)
	(5 6 7 8 9)
	> (iota 5 3 19)
	(5 8 11 14 17)
	> (iota 1 2 3 4)
	procedure iota: expects 1-3 arguments, given 4
	> 

+---------------
| So it's maybe "concise" but it's far from "expressive" in the sense
| that I mean it, which is specifically "focusing on terminology that
| expresses rather than implements an idea".  That doesn't mean 
| syntactically minimal.  For example, if you could say 
|    (mymap  f lst step: cddr)
| that would be an improvement in the domain of language expressivity.
+---------------

Well, of course Scheme doesn't have CL-style keywords, but using a common
helper routine (such as mentioned above), the Elk implementation used
normal symbols as "keywords" in its X Windows binding, so you wrote code
that tended to look like this ["parse-geometry" was my own routine to crack
an X command line "-geom 40x30+123+456"]:

  (let-values (((width height x y) (parse-geometry geom-arg)))
    (let* ((dpy (open-display))
           (black (black-pixel dpy))
           (white (white-pixel dpy))
           (win (create-window 'parent (display-root-window dpy)
                               'width width 'height height 'x x 'y y
                               'background-pixel white
                               'border 0
                               'event-mask '(exposure)))
           (gc (create-gcontext 'window win 'function 'xor
                                'background black 'foreground white))
           ...)
      (set-wm-normal-hints! 'window win
			    'width width 'height height 'x x 'y y)
      ... )

Those "keyword/value" pairs really were order-independent, so one could
equally well have written:

         (create-gcontext 'foreground white 'function 'xor
                          'background black 'window win)

Is that the kind of thing you're talking about?


-Rob

-----
Rob Warnock, 31-2-510		····@sgi.com
Network Engineering		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043
From: Rob Warnock
Subject: Re: distinction?
Date: 
Message-ID: <90i590$6dsn4$1@fido.engr.sgi.com>
Kent M Pitman  <······@world.std.com> wrote:
+---------------
| Had they been taught the fact of "choice" in Scheme class, I'd gladly 
| allow them that choice.  But since they were taught dogma, it just pisses
| me off that they walk into a CL shop with a deathwish for perfectly 
| perspicuous iteration constructs like dotimes and dolist...
+---------------

Hee hee! Even when coding in Scheme, I use "dotimes" and "dolist" and
subsets of "destructuring-bind" and "multiple-value-bind" and lots of
other neat ideas borrowed from CL. But then, I write my Scheme macros
with "defmacro", too...  ;-}


-Rob (the "Common Scheme" heretic)

-----
Rob Warnock, 31-2-510		····@sgi.com
Network Engineering		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043
From: felix
Subject: Re: distinction?
Date: 
Message-ID: <t2lsenfq369ld2@corp.supernews.com>
Kent M Pitman wrote in message ...
>
>I don't mind that people teach people the relation between recursion and
>teach "alternatives", not "dogma".  And the Scheme community is, for
whatever
>reason, rich with dogma.

>


And *this* in comp.lang.lisp! I just can't stop laughing! ;-)


felix
From: Frankque
Subject: Re: distinction?
Date: 
Message-ID: <3a2afad9@news.infinetgroup.com>
"felix" <·····@anu.ie> wrote in message
···················@corp.supernews.com...
>
> Kent M Pitman wrote in message ...
> >
> >I don't mind that people teach people the relation between recursion and
> >teach "alternatives", not "dogma".  And the Scheme community is, for
> whatever
> >reason, rich with dogma.
>
> >
>
>
> And *this* in comp.lang.lisp! I just can't stop laughing! ;-)
>
>
> felix
>
> Laughing might be the side effect of the establishment of this forum;-(
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwk89guavn.fsf@world.std.com>
"felix" <·····@anu.ie> writes:

> Kent M Pitman wrote in message ...
>
> >I don't mind that people teach people the relation between
> >recursion and teach "alternatives", not "dogma".  And the 
> >Scheme community is, for whatever reason, rich with dogma.
>
> And *this* in comp.lang.lisp! I just can't stop laughing! ;-)

I'm afraid I'm missing a joke here.  Is there some major piece of 
dogma being routinely pushed here that I'm not aware of?  As with
any community made of human beings, it's hard to generalize fully
to say we always or never do a thing, but overall I'd say that this
community is rich in tolerance for multiple ways to do a thing...
certainly compared to most other language communities I can think of.
If you disagree, I'd be fascinated to hear why.
From: Erik Naggum
Subject: Re: distinction?
Date: 
Message-ID: <3184845254046912@naggum.net>
* "Frankque" <········@infinet.net>
| I know Scheme is a dialect of Lisp.

  The Lisp that Scheme is a "dialect" of is akin to the Indo-European
  that both English and Swahili could be described as "dialects" of.
  These "dialects" have diverged so much it is now useless to think of
  the Lisp of which Scheme was supposedly a dialect as something that
  still exists.  The Lisp community continued to evolve after Scheme
  split off to go their own way.  Scheme is in my view much closer to a
  dialect of Algol with some Lisp heritage.

#:Erik
-- 
  "When you are having a bad day and it seems like everybody is trying
   to piss you off, remember that it takes 42 muscles to produce a
   frown, but only 4 muscles to work the trigger of a good sniper rifle."
								-- Unknown
From: Lieven Marchand
Subject: Re: distinction?
Date: 
Message-ID: <m3aeadmohj.fsf@localhost.localdomain>
Erik Naggum <····@naggum.net> writes:

>   The Lisp that Scheme is a "dialect" of is akin to the Indo-European
>   that both English and Swahili could be described as "dialects" of.

For some value of Indo-European. Swahili is a Niger-Congo language
that noone I'm familiar with has ever claimed any relationship to
Indo-European for. 

-- 
Lieven Marchand <···@bewoner.dma.be>
Lambda calculus - Call us a mad club
From: Erik Naggum
Subject: Re: distinction?
Date: 
Message-ID: <3184871320724740@naggum.net>
* Lieven Marchand <···@bewoner.dma.be>
| For some value of Indo-European. Swahili is a Niger-Congo language
| that noone I'm familiar with has ever claimed any relationship to
| Indo-European for. 

  Hence the last sentence, as in "dialect of Algol".

#:Erik
-- 
  "When you are having a bad day and it seems like everybody is trying
   to piss you off, remember that it takes 42 muscles to produce a
   frown, but only 4 muscles to work the trigger of a good sniper rifle."
								-- Unknown
From: Christopher C Stacy
Subject: Re: distinction?
Date: 
Message-ID: <x8l1yvozv1i.fsf@world.std.com>
>>>>> On 03 Dec 2000 17:57:44 +0100, Lieven Marchand ("Lieven") writes:

 Lieven> Erik Naggum <····@naggum.net> writes:
 >> The Lisp that Scheme is a "dialect" of is akin to the Indo-European
 >> that both English and Swahili could be described as "dialects" of.

 Lieven> For some value of Indo-European. Swahili is a Niger-Congo language
 Lieven> that noone I'm familiar with has ever claimed any relationship to
 Lieven> Indo-European for. 

Yes, Kiswahili is basically Bantu with some Arabic words (such as
"Swahili", derived from the Arabic word for "coastal"!)
From: Kellom{ki Pertti
Subject: Re: distinction?
Date: 
Message-ID: <xfzu28jnlud.fsf@korppi.cs.tut.fi>
Erik Naggum <····@naggum.net> writes:
>   Scheme is in my view much closer to a
>   dialect of Algol with some Lisp heritage.

I have always been curious as to why you think so. My problems
when I switch from Scheme to Common Lisp and back seem to be very
superficial, e.g. whether to write "define" or "defun", whether to use
#' or not etc. Otherwise the difference does not seem to be that big,
and certainly the same mindset works for both languages.

Admittedly I am more familiar with Scheme than CL, so maybe my coding
style is just closer to some premordial proto-Lisp. However, to me the
similarities of the languages greatly outhweigh the differences. For
example, I view the issue of namespaces as largely irrelevant to
whether something is a Lisp or not.

The language communities and the typical way in which the languages
are used are quite different in many respects, but on technical
grounds Scheme and Common Lisp seem very similar to me.
-- 
Pertti Kellom\"aki, Tampere Univ. of Technology, Software Systems Lab
From: Erik Naggum
Subject: Re: distinction?
Date: 
Message-ID: <3185032506447343@naggum.net>
* Kellom{ki Pertti <··@korppi.cs.tut.fi>
| I have always been curious as to why you think so. My problems
| when I switch from Scheme to Common Lisp and back seem to be very
| superficial, e.g. whether to write "define" or "defun", whether to use
| #' or not etc. Otherwise the difference does not seem to be that big,
| and certainly the same mindset works for both languages.

  Well, that latter point is why you have no problems, but I can't write
  the kind of things I write in Common Lisp in Scheme at all.  If you
  write in a tiny little subset of Common Lisp that translates well into
  Scheme, you are simply not using Common Lisp very well, or, unlikely,
  you have built a Common Lisp inside Scheme, but that's such a waste
  that I can't believe anyone would do that, and I have never heard of
  anyone doing it, either.

| Admittedly I am more familiar with Scheme than CL, so maybe my coding
| style is just closer to some premordial proto-Lisp.

  It could be that you're simply writing Scheme in Common Lisp.  I have
  seen too many (reasonably) bright students who were first exposed to
  Scheme who never got out of the Scheme mindset, despite consistent and
  insistent cajoling and significant encouragement to learn to think
  more in Common Lisp terms when using Common Lisp.  The misguided idea
  that languages should be small seems to stick with them so much that
  at some level they refuse to learn more than some misconception of a
  "core" Common Lisp, and prefer to write out most everything else by
  hand whenever they need it.  (We see the same in some Common Lisp
  programmers who have a strong, irrational desire never to use loop,
  even where it is far more expressive and compact and efficient than
  whatever they write by hand.)

| The language communities and the typical way in which the languages
| are used are quite different in many respects, but on technical
| grounds Scheme and Common Lisp seem very similar to me.

  It is on technical grounds they are the least similar.  Superficially,
  the syntax and the names of many operators makes it possible to become
  and remain confused, since nothing else is similar to them, but if you
  see someone using, say, defun _inside_ a function, you just know they
  have not outgrown Scheme, yet.  There are so many traps and pitfalls
  between the two languages that one is better served thinking they are
  not similar at all.  Otherwise, you write code that uses each language
  to such a small extent that you could use just about _any_ language.

#:Erik
-- 
  "When you are having a bad day and it seems like everybody is trying
   to piss you off, remember that it takes 42 muscles to produce a
   frown, but only 4 muscles to work the trigger of a good sniper rifle."
								-- Unknown
From: Frankque
Subject: Re: distinction?
Date: 
Message-ID: <3a2d4a2c@news.infinetgroup.com>
Interesting issue! It seems out of scope because the preference and
experience make people so different in thinking of the same things  that any
consensus would remain a dream. Pathetic perfectionism would make the world
better?

Frankque
"Erik Naggum" <····@naggum.net> wrote in message
·····················@naggum.net...
> * Kellom{ki Pertti <··@korppi.cs.tut.fi>
> | I have always been curious as to why you think so. My problems
> | when I switch from Scheme to Common Lisp and back seem to be very
> | superficial, e.g. whether to write "define" or "defun", whether to use
> | #' or not etc. Otherwise the difference does not seem to be that big,
> | and certainly the same mindset works for both languages.
>
>   Well, that latter point is why you have no problems, but I can't write
>   the kind of things I write in Common Lisp in Scheme at all.  If you
>   write in a tiny little subset of Common Lisp that translates well into
>   Scheme, you are simply not using Common Lisp very well, or, unlikely,
>   you have built a Common Lisp inside Scheme, but that's such a waste
>   that I can't believe anyone would do that, and I have never heard of
>   anyone doing it, either.
>
> | Admittedly I am more familiar with Scheme than CL, so maybe my coding
> | style is just closer to some premordial proto-Lisp.
>
>   It could be that you're simply writing Scheme in Common Lisp.  I have
>   seen too many (reasonably) bright students who were first exposed to
>   Scheme who never got out of the Scheme mindset, despite consistent and
>   insistent cajoling and significant encouragement to learn to think
>   more in Common Lisp terms when using Common Lisp.  The misguided idea
>   that languages should be small seems to stick with them so much that
>   at some level they refuse to learn more than some misconception of a
>   "core" Common Lisp, and prefer to write out most everything else by
>   hand whenever they need it.  (We see the same in some Common Lisp
>   programmers who have a strong, irrational desire never to use loop,
>   even where it is far more expressive and compact and efficient than
>   whatever they write by hand.)
>
> | The language communities and the typical way in which the languages
> | are used are quite different in many respects, but on technical
> | grounds Scheme and Common Lisp seem very similar to me.
>
>   It is on technical grounds they are the least similar.  Superficially,
>   the syntax and the names of many operators makes it possible to become
>   and remain confused, since nothing else is similar to them, but if you
>   see someone using, say, defun _inside_ a function, you just know they
>   have not outgrown Scheme, yet.  There are so many traps and pitfalls
>   between the two languages that one is better served thinking they are
>   not similar at all.  Otherwise, you write code that uses each language
>   to such a small extent that you could use just about _any_ language.
>
> #:Erik
> --
>   "When you are having a bad day and it seems like everybody is trying
>    to piss you off, remember that it takes 42 muscles to produce a
>    frown, but only 4 muscles to work the trigger of a good sniper rifle."
> -- Unknown
From: Kellom{ki Pertti
Subject: Re: distinction?
Date: 
Message-ID: <xfz4s0h501n.fsf@korppi.cs.tut.fi>
Erik Naggum <····@naggum.net> writes:
>   Well, that latter point is why you have no problems, but I can't write
>   the kind of things I write in Common Lisp in Scheme at all. 

Could you elaborate on that? I am specifically trying to understand
why you classify Scheme more as a dialect of Algol than as a dialect
of Lisp. Clearly Scheme lacks many features that are present in Common
Lisp, but I would like to know if there are specific distinguishing
features, or is it just the general absence of many features that
makes the difference.

>   It could be that you're simply writing Scheme in Common Lisp.  I have
>   seen too many (reasonably) bright students who were first exposed to
>   Scheme who never got out of the Scheme mindset, despite consistent and
>   insistent cajoling and significant encouragement to learn to think
>   more in Common Lisp terms when using Common Lisp.

The project I am working on in a small compiler for a research
project. I am using CLOS, the compiler is not full of tail recursive
functions and there is a setf here and there, so I could not convert
it to Scheme just by replacing "defun" by "define". I am happy about
the extra convenience, but it certainly does not feel like I am coming
from Algol to Lisp.

>   There are so many traps and pitfalls
>   between the two languages that one is better served thinking they are
>   not similar at all.  Otherwise, you write code that uses each language
>   to such a small extent that you could use just about _any_ language.

This may be good advice for someone who is trying to learn the
languages, but has little to do with how related they actually are.
-- 
Pertti Kellom\"aki, Tampere Univ. of Technology, Software Systems Lab
From: Xenophon Fenderson the Carbon(d)ated
Subject: Re: distinction?
Date: 
Message-ID: <w4o8zptxsiq.fsf@lovecraft.irtnog.org>
>>>>> "Kellom{ki" == Kellom{ki Pertti <··@korppi.cs.tut.fi> writes:

    Kellom{ki> Could you elaborate on that? I am specifically trying
    Kellom{ki> to understand why you classify Scheme more as a dialect
    Kellom{ki> of Algol than as a dialect of Lisp.

When I heard that comparison, I thought it was because Scheme is
lexically scoped, like Algol (and all the Algol descendents I know,
e.g. Pascal, C, Java).  Common Lisp supports both dynamic scope
(for historical reasons?) and lexical scope.

-- 
"Die, spork user! And burn in fiery torment!" -- Handy, the Handpuppet of Doom
From: Espen Vestre
Subject: Re: distinction?
Date: 
Message-ID: <w6zoi8zlj6.fsf@wallace.ws.nextra.no>
········@irtnog.org (Xenophon Fenderson the Carbon(d)ated) writes:

> Common Lisp supports both dynamic scope (for historical reasons?)

dynamic scope is so useful that you don't want it just for historical
reasons.
-- 
  (espen)
From: Xenophon Fenderson the Carbon(d)ated
Subject: Re: distinction?
Date: 
Message-ID: <w4o3dg0xn39.fsf@lovecraft.irtnog.org>
>>>>> "Espen" == Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

    Espen> dynamic scope is so useful that you don't want it just for
    Espen> historical reasons.

I'm pretty clueless when it comes to dynamic scope.  Why is it so
useful?  I doubt I understand even what dynamic scope really is.  I
grew up using Scheme, so I'm used to DEFINE creating a binding in the
top-most environment.  I fail to see how dynamic scope is any different
from top-most-level bindings, although dynamic bindings established in
one function can affect another, right?

-- 
"Die, spork user! And burn in fiery torment!" -- Handy, the Handpuppet of Doom
From: Joe Marshall
Subject: Re: distinction?
Date: 
Message-ID: <itow85gh.fsf@content-integrity.com>
········@irtnog.org (Xenophon Fenderson the Carbon(d)ated) writes:

> >>>>> "Espen" == Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:
> 
>     Espen> dynamic scope is so useful that you don't want it just for
>     Espen> historical reasons.
> 
> I'm pretty clueless when it comes to dynamic scope.  Why is it so
> useful?  I doubt I understand even what dynamic scope really is.  I
> grew up using Scheme, so I'm used to DEFINE creating a binding in the
> top-most environment.  I fail to see how dynamic scope is any different
> from top-most-level bindings, although dynamic bindings established in
> one function can affect another, right?

Suppose there were a special (dynamic) variable called *LOCALE* that
determines (among other things) the language used for printing certain
messages. 

When I run some complicated program 

(complicated-program)

the messages are printed out in English.

However, I could write
  (let ((*locale* :freedonia))
    (complicated-program))

and see the messages in `Freedonese'.

It is as if you SETQ'd the variable to :freedonia for the duration of
the call to (complicated-program) and then SETQ'd it back to the
default value when you were done.  (The difference being that you
cannot `accidently forget' to SETQ it back.  If you have multiple
threads, there are more complications.)

Dynamic scope is just the right tool when you wish to model certain
kinds of `global' state.


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----
From: Nathan Froyd
Subject: Re: distinction?
Date: 
Message-ID: <slrn92vgcf.22t.froydnj@froyd3.laptop.rose-hulman.edu>
In article <···············@lovecraft.irtnog.org>, Xenophon Fenderson the Carbon(d)ated wrote:
>I'm pretty clueless when it comes to dynamic scope.  Why is it so
>useful?  I doubt I understand even what dynamic scope really is.  I
>grew up using Scheme, so I'm used to DEFINE creating a binding in the
>top-most environment.  I fail to see how dynamic scope is any different
>from top-most-level bindings, although dynamic bindings established in
>one function can affect another, right?

You could say, for example, something like:

(defun read-floating-point-numbers ()
  (let ((*read-default-float-format* 'double-float))
    .....))

and then all the functions you called from READ-FLOATING-POINT-NUMBERS
would use the value of *READ-DEFAULT-FLOAT-FORMAT*, which might be
fairly useful.  Pick your favorite global variable for other examples
(like *WARN-ON-FLOATING-POINT-CONTAGION* or something).

In Scheme, you'd have to do fluid-let or something similar.
-- 
</nathan>  ·······@rose-hulman.edu  |  http://www.rose-hulman.edu/~froydnj/

Yes, God had a deadline.  So He wrote it all in Lisp.
From: ········@hex.net
Subject: Re: distinction?
Date: 
Message-ID: <wkk89c3tzu.fsf@441715.i-did-not-set--mail-host-address--so-shoot-me>
>>>>> "XF" == Xenophon Fenderson the Carbon(d)ated <········@irtnog.org> writes:
>>>>> "Espen" == Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:
Espen> dynamic scope is so useful that you don't want it just for
Espen> historical reasons.

XF> I'm pretty clueless when it comes to dynamic scope.  Why is it so
XF> useful?  I doubt I understand even what dynamic scope really is.
XF> I grew up using Scheme, so I'm used to DEFINE creating a binding
XF> in the top-most environment.  I fail to see how dynamic scope is
XF> any different from top-most-level bindings, although dynamic
XF> bindings established in one function can affect another, right?

The merit of dynamic scope is that it means that you can make use of
bindings that appear and disappear as needed, and have them pass
through to be used by whichever functions _need_ to use them without
needing to explicitly declare them _everywhere_.

For instance, if customizing Emacs, you're going to have code that has
to manipulate the point and the screen view.  

If those are bound using lexical scoping, then in order for a function
to access point two layers down, you'll have to explicitly pass point
around.

;;; With lexical scoping...
(defun foo (this)
  (let ((save-point point))
    (bar stuff point)
    (setf point save-point)))

(defun bar (stuff point)
  (do-something)
  (fooz point))

(defun fooz (point)
  (up-row point) ;;; Do something with point
  (insert-text "blah")
  (down-row point))

;;; With dynamic scoping
(defun foo (this)
  (let ((save-point point))
    (bar stuff)
    (setf point save-point)))

(defun bar (stuff)
  (do-something)
  (fooz))

(defun fooz () ;; Doesn't need point as an argument
  (up-row point)  ;; Points to the point that's in foo
  (insert-text "blah")
  (down-row point))
  
The point (to overuse the word :-)) here is that with lexical scope,
anything that is not explicitly declared is _invisible_, which means
you have to name anything that you want passed on.

With dynamic scope, the fact that function bar didn't _use_ point
means that the programmer is not afflicted with the need to declare
its existence for the (rather artificial) reason that "you know one of
the children uses it."
-- 
(concatenate 'string "cbbrowne" ·@hex.net")
<http://www.ntlug.org/~cbbrowne/>
"Windows  has detected  that a  gnat  has farted  near your  computer.
Press any key to reboot." --- Simon Oke in the scary devil monastery
From: Erik Naggum
Subject: Re: distinction?
Date: 
Message-ID: <3185228750011668@naggum.net>
* Xenophon Fenderson the Carbon(d)ated
| I'm pretty clueless when it comes to dynamic scope.

  At least you recognize that.  A lot of Scheme people think they know
  everything about dynamic scope when they are clueless about it.

| Why is it so useful?

  Because it embodies intrinsic language support for the protocol that
  surrounds every _sane_ use of global variables (or more precisely,
  variables with indefinite scope -- referenceable from everywhere).
  Namely, if you bind a special variable, you are guaranteed that it
  will be restored to the value it had when you entered the dynamic
  extent when you exit that scope, regardless of errors, signals, non-
  local transfers of control, anything.  Implementing this yourself is
  terribly hard and can get so low-level most programmers and language
  designers alike just give up and live with errors in restoring the old
  value.  Typically, however, you don't even _have_ binding forms for
  global variables in languages that do not support special variables,
  so you end up _having_ to use a local copy and set and restore the
  global variable yourself.

(let ((*print-base* 16))
  ...)

  is in principle functionally similar to this:

(let ((old-print-base *print-base*))
  (unwind-protect
      (progn
        (setq *print-base* 16)
        ....)
    (setq *print-base* old-print-base)))

  although the differences will be very noticeable if you have parallel
  bindings, such as you have in a multiprocessing environment, with one
  binding per thread/process of this variable.  Special variable binding
  takes care of all this.

| i doubt I understand even what dynamic scope really is.

  Well, it's a misnomer, so that's not so strange.  "Dynamic scope" is
  short-hand for "indefinite scope, dynamic extent".  That is, you can
  value from anywhere (indefinite/global scope), but that particular
  binding extends from binding establishment through disestablishment,
  which looks just like a lexical binding in that it covers only so much
  code, but because of the indefinite scope, it actually covers all code
  that gets executed between binding establishment and disestablishment.

| I grew up using Scheme, so I'm used to DEFINE creating a binding in
| the top-most environment.

  Well, this is one instance of what I consider damaging in premature
  exposure to Scheme.  It is too damn low-level and _unevolved_ as a
  language, yet it looks amazingly complex and rich through its simple
  elegance (which fools mostly any intellectual, just like simple and
  elegant and wrong political theories trap bright students) until you
  start to figure out the kind of complexity the real world needs.

| I fail to see how dynamic scope is any different from top-most-level
| bindings, although dynamic bindings established in one function can
| affect another, right?

  I hope this has helped.

#:Erik
-- 
  "When you are having a bad day and it seems like everybody is trying
   to piss you off, remember that it takes 42 muscles to produce a
   frown, but only 4 muscles to work the trigger of a good sniper rifle."
								-- Unknown
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfw1yvjm6sg.fsf@world.std.com>
Erik Naggum <····@naggum.net> writes:

> | Why is [a special variable facility] so useful?
> 
>   ... Implementing this yourself is terribly hard and can get so 
>   low-level most programmers and language designers alike just give
>   up and live with errors in restoring the old value. ...

Some good points made by Erik, in neatly precise form, but I want to add
one thing.

Some Scheme implementations offer DYNAMIC-WIND, which is the generalization
of special variable binding at the data level.  They tend to stop short of
providing syntax to make it as convenient as CL's specials, but it does 
offer more power.  (Also, there's some question as to whether it is as 
efficient as CL's specials, but there we're talking constant factors and
specific implementations, and I won't go there.)

  (DYNAMIC-WIND winder unwinder body)

calls winder (a function of no arguments) to set up for the body, then
calls unwinder (a function again of no arguments) to unset the body.
It's allowed to do this as many times as needed, not just at start and
end of body, and can be used to implement the part of process
scheduling that unwinds special variable bindings (as well as other
dynamic bindings custom to the user's applications) on a process
switch.  Often these two functions, winder and unwinder, are the same
function, since often the action to do is to exchange a hidden
location (e.g., a stack slot or closure variable holding the saved
value) with a visible location (e.g., a dynamic value cell).

As I recall, this primitive was first suggested in a little-known paper
by Steele called "Macaroni is better than Sphaghetti".

It's really too bad CL hasn't picked up this operator.  It's quite
cool and very useful.  CLIM needs it desperately, for example.  You
need it to implement LETF.  The original implementors of CLIM
substituted UNWIND-PROTECT and crossed their fingers CLIM would be
running in a single process, but that was a bad assumption and left
CLIM not threadsafe in a bunch of really critical places that I hope
(but somehow doubt) have been fixed by now.
From: Rob Warnock
Subject: Re: distinction?
Date: 
Message-ID: <90te91$8r0ao$1@fido.engr.sgi.com>
Kent M Pitman  <······@world.std.com> wrote:
+---------------
| Some Scheme implementations offer DYNAMIC-WIND, which is the generalization
| of special variable binding at the data level.  They tend to stop short of
| providing syntax to make it as convenient as CL's specials, but it does 
| offer more power.
+---------------

Several Scheme implementations also offer "fluid-let", which is much
more convenient to use than dynamic-wind if all you need is just
dynamic binding of variables. Fluid-let interacts correctly with
dynamic-wind (not surprising, since it's usually implemented using it).

MzScheme, in particular, also provides a mechanism called "parameters"
<URL:http://www.cs.rice.edu/CS/PLT/packages/doc/mzscheme/node98.htm>,
procedures that store some value inside themselves [for example,
"current-output-port"]; and a "parameterize" form, which does a
sort of fluid-let for parameters.

+---------------
|   (DYNAMIC-WIND winder unwinder body)
| 
| calls winder (a function of no arguments) to set up for the body, then
| calls unwinder (a function again of no arguments) to unset the body.
+---------------

Actually, following the minutes of the June '92 meeting, R5RS ordered
the arguments slightly differently:

    (dynamic-wind before body after)

+---------------
| It's allowed to do this as many times as needed, not just at start and
| end of body, and can be used to implement the part of process
| scheduling that unwinds special variable bindings (as well as other
| dynamic bindings custom to the user's applications) on a process switch.
+---------------

The last time this topic came up, you also implied that dynamic-wind
was useful only for process switching, but it's far more general
than that. It's also useful wherever call/cc is used, e.g., doing
backtracking/nondeterminism, implementing "generators", for implementing
fluid-let, and as the basis of an exception system.

*Unfortunately* for the latter use, two things are missing from
the Scheme spec [though provided in most reasonable implementations]:
(1) There is no guarantee that primitive errors (e.g., divide-by-zero)
will use call/cc to throw the error, thus there's no guarantee that the
"after" thunk of dynamic-winds will be executed on errors; and (2) even
if #1 were fixed, R5RS says "The effect of using a captured continuation
to enter or exit the dynamic extent of a call to before or after is
undefined", which means that strictly speaking you can't use dynamic-wind
to implement "catch" or exception restarts. That is, the following code
isn't guaranteed to work:

	(define (eval-safely expr)
	  (let ((done #f))
	    (call/cc
	      (lambda (k)
		(dynamic-wind
		  (lambda () #f)
		  (lambda () (let ((val (eval expr)))
			       (set! done #t)
			       val))
		  (lambda () (when (not done) (k 'caught-error))))))))

Fortunately, in most Schemes, it does work:  ;-}

	> (eval-safely '(+ 1 2))
	3
	> (eval-safely '(/ 1 0))
	/: division by zero
	caught-error
	> 


-Rob

-----
Rob Warnock, 31-2-510		····@sgi.com
Network Engineering		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043
From: Boris Schaefer
Subject: Re: distinction?
Date: 
Message-ID: <87y9xpvhte.fsf@qiwi.uncommon-sense.net>
Kent M Pitman <······@world.std.com> writes:

| As I recall, this primitive was first suggested in a little-known paper
| by Steele called "Macaroni is better than Sphaghetti".

Is this available online somewhere?  Some time ago I looked for this
on the web and didn't find it.

Boris

-- 
·····@uncommon-sense.net - <http://www.uncommon-sense.net/>

QOTD:
	"It was so cold last winter that I saw a lawyer with his
	hands in his own pockets."
From: Paolo Amoroso
Subject: Re: distinction?
Date: 
Message-ID: <rF4zOpxDJxCr7t3eN=Lyo2h+gCc1@4ax.com>
On Fri, 8 Dec 2000 12:33:35 GMT, Kent M Pitman <······@world.std.com>
wrote:

>   (DYNAMIC-WIND winder unwinder body)
[...]
> It's really too bad CL hasn't picked up this operator.  It's quite
> cool and very useful.  CLIM needs it desperately, for example.  You

Can DYNAMIC-WIND be implemented from user code? Is it better to leave it to
Common Lisp implementors? Or maybe it can be implemented from user code,
but it requires low level primitives that may not be available on most
Common Lisp systems? If so, what kind of primitives?


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: Kent M Pitman
Subject: Re: distinction?
Date: 
Message-ID: <sfwsnnw761x.fsf@world.std.com>
Paolo Amoroso <·······@mclink.it> writes:

> On Fri, 8 Dec 2000 12:33:35 GMT, Kent M Pitman <······@world.std.com>
> wrote:
> 
> >   (DYNAMIC-WIND winder unwinder body)

I've been corrected that the argument order is 
 (DYNAMIC-WIND winder body unwinder)

> [...]
> > It's really too bad CL hasn't picked up this operator.  It's quite
> > cool and very useful.  CLIM needs it desperately, for example.  You
> 
> Can DYNAMIC-WIND be implemented from user code?

I don't see how.  People said this about the error system, too.  Sure, 
you can write your own dialect of Lisp in Lisp, if that's what you mean.
But the problem is that the system you're writing in won't call it.
So when processes switch (unless YOU wrote the process scheduler), 
dynamic-wind's winder and unwinder won't get called.

> Is it better to leave it to Common Lisp implementors?

Yes.

> Or maybe it can be implemented from user code,
> but it requires low level primitives that may not be available on most
> Common Lisp systems? If so, what kind of primitives?

You could fake most of it.  Something like:

 (defun dynamic-wind (wind main unwind)
   (let ((*winders* (cons wind *winders*))
         (*unwinders* (cons unwind *unwinders*)))
      (unwind-protect (progn (funcall wind) (funcall main))
        (funcall unwind))))

 (defun unwind-process (process) 
   (mapcar #'funcall
           (circular-list process)
           (symbol-value-in-process process '*unwinders*)))

 (defun wind-process (process) 
   (mapcar #'funcall-in-process
           (circular-list process)
           (symbol-value-in-process process '*winders*)))

But the parts that would not work right are:

 (a) the system wouldn't call wind-process and unwind-process on
     process switching

 (b) as you ran unwinders and winders, you'd be running in some dynamic
     environment.  i think the winders might assume the dynamic environment
     they were established in, which is why i did the funcall-in-process
     thing, to emphasize that.  but if you do it that way, you're not 
     going to remove special variable bindings, because you're not the 
     system.  so the 2nd to nth elements of the list will get funcalled
     with the wrong dynamic bindings.   you could, alternatively, say they
     get run in the null dynamic environment (i.e., from another
     process) although that would presuppose a process switch had already
     happened and would beg the question of how.  scheme doesn't really
     do much with dynamic environments, as i recall (though maybe i'm
     misremembering) so I *think* this issue doesn't come up. you could
     also disallow relying on dynamic state in winders and unwinders, if
     you thought programmers had a lot of self-discipline. (i don't.
     they abused this kind of restriction a lot in COMPILER-LET back when
     we had that.)
From: Tim Bradshaw
Subject: Re: distinction?
Date: 
Message-ID: <nkjlmtm7tch.fsf@tfeb.org>
Kent M Pitman <······@world.std.com> writes:

> 
> It's really too bad CL hasn't picked up this operator.  It's quite
> cool and very useful.  CLIM needs it desperately, for example.  You
> need it to implement LETF.  The original implementors of CLIM
> substituted UNWIND-PROTECT and crossed their fingers CLIM would be
> running in a single process, but that was a bad assumption and left
> CLIM not threadsafe in a bunch of really critical places that I hope
> (but somehow doubt) have been fixed by now.

Unfortunately DYNAMIC-WIND is really just digging yourself deeper into
the hole you're already in.  You can use DYNAMIC-WIND to take a
program which isn't thread-safe on a uniprocessor and convert it into
something which isn't thread-safe on a multiprocessor.  What you
actually want to do is write multithreaded programs in a way that they
don't have dependencies on things like the existence of some kind of
`context switch' event to trigger DYNAMIC-WIND's thunks, or that
WITHOUT-INTERRUPTS / WITHOUT-PREEMPTION is a cheap operation.

The underlying problem here seems to be that a thread in a
multithreaded system wants to `bind' things by altering global state
(which is my memory of what LETF did) and that just can't work on a
multiprocessor: you need a different design.

Of course we're all let off by the fact that there aren't actually any
multiprocessor Lisps...

--tim
From: Lieven Marchand
Subject: Re: distinction?
Date: 
Message-ID: <m3itoxv7fe.fsf@localhost.localdomain>
Kellom{ki Pertti <··@korppi.cs.tut.fi> writes:

> Erik Naggum <····@naggum.net> writes:
> >   Well, that latter point is why you have no problems, but I can't write
> >   the kind of things I write in Common Lisp in Scheme at all. 
> 
> Could you elaborate on that? I am specifically trying to understand
> why you classify Scheme more as a dialect of Algol than as a dialect
> of Lisp. Clearly Scheme lacks many features that are present in Common
> Lisp, but I would like to know if there are specific distinguishing
> features, or is it just the general absence of many features that
> makes the difference.

I don't know whether Erik has this in mind, but one of the fundamental
differences between Scheme and Common Lisp, is that in Scheme a
program is defined in terms of sequences of ASCII characters, while in
CL a program is considered as a Lisp datastructure, viz. a list of
atoms. This datastructure gets build by the CL reader. This may seem
like a rather trivial difference, but it has a far reaching influence
on language usage, things like DEFMACRO versus hygienic macros, an
extendible reader, packages etc.

-- 
Lieven Marchand <···@bewoner.dma.be>
Lambda calculus - Call us a mad club