From: David Gadbois
Subject: Repeated lambda variables
Date: 
Message-ID: <w0ksodoian6.fsf@lagavulin.cyc.com>
Is ((LAMBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?  The HyperSpec
does not appear to have an answer.

The arguments against it being legal basically boil down to allowing
implementations to note specifically what is almost certainly a
programming error.

The arguments for it being legal are 1) It does not appear to be ruled
out; and 2) There is a sensible interpretation of what it means (the
rightmost binding shadows any to the left of it.)

On the implementation front, both the Genera 8.3 and CMU CL 18a
interpreters and compilers give an error about the repeated variable.
The clisp and LispWorks interpreters return 2, and their compilers
issue warnings about the variable FOO (presumably the first one) not
being used.

--David Gadbois

From: Rainer Joswig
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <joswig-0601991915340001@pbg3.lavielle.com>
In article <···············@lagavulin.cyc.com>, David Gadbois <·······@lagavulin.cyc.com> wrote:

> Is ((LAMBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?  The HyperSpec
> does not appear to have an answer.
> 
> The arguments against it being legal basically boil down to allowing
> implementations to note specifically what is almost certainly a
> programming error.
> 
> The arguments for it being legal are 1) It does not appear to be ruled
> out; and 2) There is a sensible interpretation of what it means (the
> rightmost binding shadows any to the left of it.)
> 
> On the implementation front, both the Genera 8.3 and CMU CL 18a
> interpreters and compilers give an error about the repeated variable.
> The clisp and LispWorks interpreters return 2, and their compilers
> issue warnings about the variable FOO (presumably the first one) not
> being used.
> 
> --David Gadbois

MCL says:

 > Error: While compiling an anonymous function :
 >        Bad lambda list : (FOO FOO)

-- 
http://www.lavielle.com/~joswig
From: Rainer Joswig
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <joswig-0601991859260001@pbg3.lavielle.com>
In article <···············@lagavulin.cyc.com>, David Gadbois <·······@lagavulin.cyc.com> wrote:

> Is ((LAMBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?  The HyperSpec
> does not appear to have an answer.
> 
> The arguments against it being legal basically boil down to allowing
> implementations to note specifically what is almost certainly a
> programming error.
> 
> The arguments for it being legal are 1) It does not appear to be ruled
> out; and 2) There is a sensible interpretation of what it means (the
> rightmost binding shadows any to the left of it.)
> 
> On the implementation front, both the Genera 8.3 and CMU CL 18a
> interpreters and compilers give an error about the repeated variable.
> The clisp and LispWorks interpreters return 2, and their compilers
> issue warnings about the variable FOO (presumably the first one) not
> being used.
> 
> --David Gadbois

MCL says:

 > Error: While compiling an anonymous function :
 >        Bad lambda list : (FOO FOO)

-- 
http://www.lavielle.com/~joswig
From: Lyman S. Taylor
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <770jgj$3pu@pravda.cc.gatech.edu>
In article <···············@lagavulin.cyc.com>,
David Gadbois  <·······@lagavulin.cyc.com> wrote:
>Is ((LAMBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?  The HyperSpec
>does not appear to have an answer.

   I guess it depends a bit upon how literally you interpret the HyperSpec

lambda list n. a list that specifies a set of parameters (sometimes called
     lambda variables) and a protocol for receiving values for 
     those parameters; 

   The first part of that defintion mentions "set".  An implication 
   that duplicates aren't allowed, IMHO.  

   I can't seem to find anything protesting about 

       (let  (  ( a 1 ) 
                ( b 2 )
                ( a 3 ) )
          a )

   either. However, I wouldn't expect any standard behaviour.


>The arguments for it being legal are 1) It does not appear to be ruled
>out; 
    
    Left out can also implicitly mean implementation specific.  Not 
    required.  The standard being larely a document for what the implementation
    must do.   

-- 

Lyman S. Taylor            "I'm a Doctor! Not a commando." 
(·····@cc.gatech.edu)         The enhanced EMH Doctor in a ST:Voyager epidsode.
From: Barry Margolin
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <oNQk2.116$Pu3.10214@burlma1-snr1.gtei.net>
In article <··········@pravda.cc.gatech.edu>,
Lyman S. Taylor <·····@cc.gatech.edu> wrote:
>In article <···············@lagavulin.cyc.com>,
>David Gadbois  <·······@lagavulin.cyc.com> wrote:
>   I can't seem to find anything protesting about 
>
>       (let  (  ( a 1 ) 
>                ( b 2 )
>                ( a 3 ) )
>          a )
>
>   either. However, I wouldn't expect any standard behaviour.

I thought I remembered this coming up, but I can't find anything in the HS,
either.  I thought that we decided that LET doesn't allow duplication,
while LET* does, but I can't find it.

>>The arguments for it being legal are 1) It does not appear to be ruled
>>out; 
>    
>    Left out can also implicitly mean implementation specific.  Not 
>    required.  The standard being larely a document for what the implementation
>    must do.   

The standard doesn't say that this is an error.  However, it is also silent
about which value the parameter variable should be bound to initially.  All
the required variables are supposed to be bound in parallel, so it's
unspecified which value it should receive.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Don't bother cc'ing followups to me.
From: Vassil Nikolov
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <3693F487.2055@poboxes.com>
David Gadbois wrote:
> 
> Is ((LAMBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?  The HyperSpec
> does not appear to have an answer.
(...)

From the HyperSpec:

  3.1.1 Introduction to Environments
  (...)
  Bindings in an environment are partitioned into namespaces. A single 
name can
  simultaneously have more than one associated binding per environment, 
but can
  have only one associated binding per namespace.
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

HyperSpec---one of the best uses of disk space.

Good luck,
Vassil.
From: David Gadbois
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <w0kogobhtep.fsf@lagavulin.cyc.com>
Vassil Nikolov <········@poboxes.com> writes:
> > Is ((LAMDBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?  The
> > HyperSpec does not appear to have an answer.
> 
> From the HyperSpec:
> 
>   3.1.1 Introduction to Environments
>   (...)
>   Bindings in an environment are partitioned into namespaces. A
>   single name can simultaneously have more than one associated
>   binding per environment, but can have only one associated binding
>   per namespace.

I would interpret the text as saying that relation NAME x ENVIRONMENT
x NAMESPACE x OBJECT is functional in OBJECT.  However, it doesn't say
anything about shadowing, which is just the question at hand:  Should
subsequent bindings of the same name in the same binding construct
shadow prior ones, or should it be an error.  We certainly would not
want to rule out:

    (let ((foo 1))
      (let ((foo 2))
        foo))


--David Gadbois
From: Lyman S. Taylor
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <772vcf$b24@pravda.cc.gatech.edu>
In article <···············@lagavulin.cyc.com>,
David Gadbois  <·······@lagavulin.cyc.com> wrote:
>Vassil Nikolov <········@poboxes.com> writes:

>>   Bindings in an environment are partitioned into namespaces. A
>>   single name can simultaneously have more than one associated
>>   binding per environment, but can have only one associated binding
>>   per namespace.
>
>I would interpret the text as saying that relation NAME x ENVIRONMENT
>x NAMESPACE x OBJECT is functional in OBJECT.

     I don't  think the above disallows either.  The nonoptional 
     arguments can be thought of as bound in parallel (as with LET).
     When there are two (or more )  identical names and both must be bound 
     in parallel some sort of serialization must occur (especailly on 
     uniprocessors machines. ;-) ).  That serialization 
     is implementation dependent. Therefore, you shouldn't write code
     that depends upon this.

     [ By the way, I now recall a "bug" report I once submited to
       Harlequin for Lispworks.  The interpreter and compiler 
       serialized the bindings for "redundant" LET names in 
       different orders.  So it wasn't even consistant in the
       same implementation. ]

     Personally, I'd at least always issue a warning if not make
     it an error.  However, it takes "time" to check for such 
     dubious code.   I don't think there is a inherently "correct"
     interpretation of this kind of code.


>shadow prior ones, or should it be an error.  We certainly would not
>want to rule out:
>
>    (let ((foo 1))
>      (let ((foo 2))
>        foo))

   Errr,  each LET above defines a new environment. So there is no
   conflict above.

   The problem is how to you serialize parallel bindings. If you
   mandate a serialization then the bindings are NOT parallel.
   
   I don't think this sort of encoding has any "utility" so totally
   diallowing is would be my vote. However, at time the lisp standards 
   don't make the implementations work as hard as they should. 


P.S.  the optional argument can have default values which depend upon the
      value of a "previous" (in left to right order) argument.  The
      nonoptional args don't quite fit in this category. 



   
-- 
					
Lyman S. Taylor                "Twinkie Cream; food of the Gods" 
(·····@cc.gatech.edu)                     Jarod, "The Pretender" 
From: Vassil Nikolov
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <369520FE.1508@poboxes.com>
David Gadbois wrote:
> 
> Vassil Nikolov <········@poboxes.com> writes:
> > > Is ((LAMDBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?  The
> > > HyperSpec does not appear to have an answer.
> >
> > From the HyperSpec:
> >
> >   3.1.1 Introduction to Environments
> >   (...)
> >   Bindings in an environment are partitioned into namespaces. A
> >   single name can simultaneously have more than one associated
> >   binding per environment, but can have only one associated binding
> >   per namespace.
> 
> I would interpret the text as saying that relation NAME x ENVIRONMENT
> x NAMESPACE x OBJECT is functional in OBJECT.  However, it doesn't say
> anything about shadowing, which is just the question at hand:  Should
> subsequent bindings of the same name in the same binding construct
> shadow prior ones, or should it be an error.

From the HyperSpec:

  3.1.3 Lambda Expressions

  In a lambda expression, the body is evaluated in a lexical
  environment that is formed by adding the binding of each parameter
  in the lambda list with the corresponding value from the arguments
  to the current lexical environment. 

I take this to mean that a lambda expression establishes a *single*
environment.  Each parameter belongs to the same namespace, that of
variables.  One environment, one namespace, therefore one binding.

Besides, the definition of shadowing implies that it takes *two*
forms to have shadowing.

-- 

Vassil Nikolov <········@poboxes.com>
(You may want to cc your posting to me if I have to see it.)
LEGEMANVALEMFVTVTVM
From: Barry Margolin
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <NG9l2.54$z15.2961@burlma1-snr1.gtei.net>
In article <·············@poboxes.com>,
Vassil Nikolov  <········@poboxes.com> wrote:
>From the HyperSpec:
>
>  3.1.3 Lambda Expressions
>
>  In a lambda expression, the body is evaluated in a lexical
>  environment that is formed by adding the binding of each parameter
>  in the lambda list with the corresponding value from the arguments
>  to the current lexical environment. 
>
>I take this to mean that a lambda expression establishes a *single*
>environment.  Each parameter belongs to the same namespace, that of
>variables.  One environment, one namespace, therefore one binding.

That quote is describing the environment in which the body is evaluated.
However, the fact that initializers for non-required parameters are allowed
to reference parameter variables that precede them in the lambda list
implies that there may be environments intermediate between the one outside
the lambda expression and the one in which the body is evaluated.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Don't bother cc'ing followups to me.
From: ········@poboxes.com
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <774mjg$n4a$1@nnrp1.dejanews.com>
Barry Margolin wrote:
>
> In article <·············@poboxes.com>,
> Vassil Nikolov  <········@poboxes.com> wrote:
> >From the HyperSpec:
> >
> >  3.1.3 Lambda Expressions
> >
> >  In a lambda expression, the body is evaluated in a lexical
> >  environment that is formed by adding the binding of each parameter
> >  in the lambda list with the corresponding value from the arguments
> >  to the current lexical environment.
> >
> >I take this to mean that a lambda expression establishes a *single*
> >environment.  Each parameter belongs to the same namespace, that of
> >variables.  One environment, one namespace, therefore one binding.
>
> That quote is describing the environment in which the body is evaluated.
> However, the fact that initializers for non-required parameters are allowed
> to reference parameter variables that precede them in the lambda list
> implies that there may be environments intermediate between the one outside
> the lambda expression and the one in which the body is evaluated.

I agree (or at least can't think of an objection) that there may be
intermediate environments (whose existence is, I suppose,
implementation dependent).

The original posting, however, was concerned with the evaluation of
the _body_: ((LAMBDA (X X) X) 1 2) ==> ?  (And in the absence of
non-required parameters.)

May I add that there are (at least) two issues here:

(1) Could we imagine a reasonable Lisp where a lambda list such
as (X X) would be legal?

(2) Can it be definitely deduced from the ANSI Common Lisp standard
that a lambda list such as (X X) is illegal?

  Note: I am not suggesting that anybody in their right mind
        should be allowed to write lambda lists like that.
        There could be contorted situations, however, where
        such a lambda list might be constructed through the
        programmatic combination of two or more lists (like
        the situations where two occurences of the same
        keyword parameter may come up in a function call
        when argument lists are appended together).

As an aside, I find I have forgotten my lambda calculus studies
and can't decide if Lxx.x is well-formed (L stands for lambda).

Maybe this whole issue is not _that_ important, but if I recall
correctly, the definitions of languages such as C and Pascal
_explicitly_ forbid the presence of two different variables
with the same name in the same scope.

Have a nice day,
Vassil.

--

Vassil Nikolov <········@poboxes.com>
(You may want to cc your posting to me if I have to see it.)
LEGEMANVALEMFVTVTVM

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    
From: Stig Hemmer
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <ekviuehcu7i.fsf@gnoll.pvv.ntnu.no>
········@poboxes.com writes:
> As an aside, I find I have forgotten my lambda calculus studies
> and can't decide if Lxx.x is well-formed (L stands for lambda).

In the Lambda calculus we studied, each lambda only took one argument.

We quickly defined a convenience notation that allowed several
arguments, but it was only as a shorthand for nested one-argument
lambdas.

So, Lxx.x would be short for (Lx(Lx.x)), a perfectly legal expression.
Applied on any argument, it would return the identity function (Lx.x)
since the inner lambda protects its x's from being substituted.  (I
have forget the usual terms for this.  Something about free variables)

In Lisp terms, (lambda (x x) x) would return its second argument if
doing things the same way as the lambda calculus _we_ learned.

On the other hand, I know there are other lambda calculi, they might
do things differently.

Stig Hemmer,
Jack of a Few Trades.
From: ········@poboxes.com
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <777fl0$4fd$1@nnrp1.dejanews.com>
I have received a private message about Lxx.x (I use L for
lambda, maybe others would find another ASCII character more
appropriate), and there has also been a posting.  I could have
figured it out myself...  Anyway, as it has been shown, we have:

  (Lxx.x)12 === (Lx.(Lx.x))12 -> (Lx.x)2 -> 2

  (and also Lxx.x === Lxy.y)

which taken literally means that

  ((lambda (x x) x) 1 2) should=> 2

and that bindings in a lambda expression should be treated
as in a LET* form and not LET.

This doesn't look quite reasonable to me especially that
in Lisp

  (lambda (x y) ...) =/= (lambda (x) (lambda (y) ...))

although it beats me if this is merely a syntactic difference.

(I am also rather curious about what McCarthy would say about
this.)

Have a nice day or night,
Vassil.


-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    
From: Rob Warnock
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <771efb$96t6r@fido.engr.sgi.com>
David Gadbois  <·······@lagavulin.cyc.com> wrote:
+---------------
| Is ((LAMBA (FOO FOO) FOO) 1 2) legal ANS Common Lisp?
+---------------

FWIW (probably not much!), I thought I'd run it by a bunch of
Schemes, too, Scheme being so much about the Lambda Calculus and all:  ;-}

These gave no error, and produced "1" as an answer:

	SIOD
	SCM
	libscheme
	SEL
	RScheme

These gave no error, and produced "2" as an answer (as CLISP does):

	TinyScheme
	MiniScheme
	Phantom
	HPP
	Scheme->C (the interpreter, might the compiler do better?)
	Scsh [the Scheme Shell, based on Scheme-48]

These gave error messages (as CMUCL does):

	Elk:
	lambda: foo: duplicate variable binding

	MzScheme:
	let: multiple bindings of "foo" in: (#%let ((foo 1) (foo 2)) foo)

	Gambit:
	*** ERROR IN [compilation] -- Duplicate parameter in parameter list
	(lambda (foo foo) foo)

	Fools' Lisp:
	Incorrect formal parameter redefinition of foo


-Rob

-----
Rob Warnock, 8L-855		····@sgi.com
Applied Networking		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
2011 N. Shoreline Blvd.		FAX: 650-964-0811
Mountain View, CA  94043	PP-ASEL-IA
From: Kent M Pitman
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <sfwogob8tcp.fsf@world.std.com>
As I reclal, and I could be wrong, repeated lambda variables were
explicitly forbidden in CLTL. I have a pretty definite and highly
elaborated memory of numerous discussions we had about possibly
changing that at X3J13.  I don't think the proposed changes succeeded,
so I bet the wording forbidding them is in there somewhere.  It could
be that it was the remark already cited by Vassil Nikolov regarding
number of associated bindings per namespace (which I agree is MOSTLY
sufficient), but I thought it said it in other places, too...

Even absent that, though, I always have to chuckle at people who
say things like "well, it's ok because it's not forbidden".  Not to
make light of someone's good faith interpretation, but really:
semantics is more than saying syntax isn't forbidden--you have to say
what is meant.  And a syntax that is not forbidden but that is assigned
no meaning can't really in any meaningful sense be permitted, unless
you want to quibble about programs like:

 ((lambda (x x) (declare (ignore x x))  3) 4 5) => 3

and whether this is reasonable, because it's clear that

 ((lambda (x x)  x) 3 4)  => ?

might return either 3 or 4.  Why?  Well,

 ((lambda (&key x) x) :x 3 :x 4)

returns 3 [because that's well-defined] and so there's precedent
for assuming that the first binding applies, but this flies in the
face of what most would say is the OBVIOUS interpretation of

 (let ((x 3)) (let* ((x (* 2 x)) (x (1+ x))) x))

which I think most people would say should yield 7.  It's LET*
where I'd expect to find the wording just plain forbidding it,
and it was all over a fight that I personally found silly which
had two components.  The first component was:

 ``We want a nice simple rule that everyone can understand.
   The rule should be "no repeated variables" and should 
   not make "subtle" distinctions like binding contours.
   It should refer to the textual shape of the code.  So even
   LET* can't take repeated variables.''

I fortunately don't remember who said this, but I'm prety
sure there were multiple people who did and they're welcome
to associate themselves with this compete put-down of the user
base if the want to.  I and others advoated a rule based on
binding contours that said it was ok for LET* but not ok for LET.

The second component of the argument, which I can only hope was
really the basis of the other argument, and is what they meant
to say instead had to do with some legitimate issues that had
to be dealt with and that I would have simply dealt with by 
definition, but that others felt were somehow something that if
we defined our way out of, we'd be admitting a wart in the
language that would somehow be omitted if we went with the
no repeated variables rule.  (Personally, I saw complete symmetry
where you were just trading one set of problems for another and
I wanted the rule to be semantic, not syntactic.)  Anyway,
the weird cases, if anyone cares, were things like:

  (let ((x ...) (x ...)) (declare (string x)) ...)

You might think that this should aply to the inner binding,
but others felt it should apply to both bindings or that it
was at least confusing. Consider specifically:

 (let* ((x 'foo) (x (symbol-name x)))
   (declare (string x))
   ...)

In my view, if the person needs to declare something, you
could just ask him to separate them out, but I felt that
the inner binding only should be the obvious thing for it to
span.  Again, I don't like the textual rule.    Here's another
more subtle one.  

 (lambda (x x) (declare (string x)) ...)

Seems like the same problem, right?  Well, not quite.  They
are in the same contour and so this should be illegal, didn't
I advocate?  Yeah, I did say that.  But think about

 (lambda (&optional x x) (declare (string x)) ...)

and even forget about the fact that the x defaults to nil.
We could make it

 (lambda (&optional (x "foo") (x "foo")) (declare (string x))...)

if that mattered to you.  But the thing you should be thinking about
instead of the stringness is the lack of parallel binding here.  
Optionals are processed like LET*, not like LET, and for all you
know so are required variables.  You think they're equivalent to
LET, but they're really not.  &KEY and &AUX variables are also
left to right.  Consider:

 (lambda (&optional (x 'foo) (x (symbol-name x))) (declare (string x)) ...)

and you'll start to see the issue.  Is it a reasonable conceptual
model to say that optionals and auxes are processed serially but requireds and
rests are processed in parallel... even when you know that there can't
be any way to prove whether the requires or rests are processed that way?
Plainly it's simpler to assume they are also serial, and then plainly
(if we can still call anything plain at this point), 

 (lambda (x x) (declare (string x x)) ...)

is like LET*, not like LET.  But this then leaves us with a funny
rule that says that in 

 ((lambda (x x &key (x x)) x) 1 2)

we should get 2 as the value since the rightmost binding should
dominate.  But we already said we have defined

 ((lambda (x x &key (x x)) x) 1 2 :x 3 :x 4)

to return 3 rather than 4 because the leftmost actual arg dominates
in a keyword pickup situation (and there's good reason to think 
this is the useful thing for reasons I won't go into, so dn't try
to say that decision was just an error).

We could make up some rule that says "rightmost vars, leftmost data"
and claim we meant it that way all along.  (A careful study might
even show there was a deep reason why it has to work out that way and
we might just barely escape with a claim of a rational meaning.)

I wanted to just define that in the case of required lambda vars
or let bindings, you can't duplicate, and only in cases where you
have argument cascading can you do it.  And I'd have compromised
down to saying that when there is a duplicated var, any declaration
needs to apply to both.  but the other camp did have a reasonable
point on this second matter.  So I think we just left things
deadlocked and preserved the CLTL wording.

But I hope I've at least put to rest the idea that if the spec
isn't 100% clear, that you can just decide that since it's not
forbidden it's ok.

It reminds me of that meeting (I think it was the Monterrey
meeting in early 1986) where Steele showed up with a couple of
pages of "trivial fixes" that he thought we'd all approve without
any question and was amazed and how many were controversial.
We learned right there that we had a hard road ahead.

 -kmp

p.s. The reason I said Vassil's citation was only mostly
     sufficient was because of this subtle issue of how
     many bindings there are in LET* and in (lambda (x x) x).
     Since a case can be made in both cases that there is
     only one binding active at a time, then repetition
     isn't forbidden under that rule.  But I think there
     is another rule somewhere to cover the exceptions.
From: Lieven Marchand
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <777ohe$pn9$2@xenon.inbe.net>
Kent M Pitman <······@world.std.com> writes:
[lots of thoughtfull commentary snipped]
> I wanted the rule to be semantic, not syntactic.)  Anyway,
> the weird cases, if anyone cares, were things like:
> 
>   (let ((x ...) (x ...)) (declare (string x)) ...)
> 
> You might think that this should aply to the inner binding,
> but others felt it should apply to both bindings or that it
> was at least confusing. Consider specifically:

How does this interact with special?

Consider
(let ((x ...) (x ...))
   (declare (special x) (string x)))

If we take your idea of allowing this for let* such a special
declaration could fold parts of your contour. Anyways, I fail to see
the utility of allowing duplication.

-- 
Lieven Marchand <···@bewoner.dma.be> 
------------------------------------------------------------------------------
Few people have a talent for constructive laziness. -- Lazarus Long
From: Christopher R. Barry
Subject: Allegro CL groks it. Re: Repeated lambda variables
Date: 
Message-ID: <87g19kow19.fsf_-_@2xtreme.net>
········@poboxes.com writes:

> I have received a private message about Lxx.x (I use L for
> lambda, maybe others would find another ASCII character more
> appropriate), and there has also been a posting.  I could have
> figured it out myself...  Anyway, as it has been shown, we have:
> 
>   (Lxx.x)12 === (Lx.(Lx.x))12 -> (Lx.x)2 -> 2
> 
>   (and also Lxx.x === Lxy.y)
> 
> which taken literally means that
> 
>   ((lambda (x x) x) 1 2) should=> 2

Under Allegro CL

USER(34): ((lambda (x x) x) 1 2)
2

CMUCL complaigns "Error: Repeated variable in lambda-list: X."

Lieven Marchand <···@bewoner.dma.be> writes:

> Kent M Pitman <······@world.std.com> writes:
> [lots of thoughtfull commentary snipped]
> > I wanted the rule to be semantic, not syntactic.)  Anyway,
> > the weird cases, if anyone cares, were things like:
> > 
> >   (let ((x ...) (x ...)) (declare (string x)) ...)
> > 
> > You might think that this should aply to the inner binding,
> > but others felt it should apply to both bindings or that it
> > was at least confusing. Consider specifically:
> 
> How does this interact with special?
> 
> Consider
> (let ((x ...) (x ...))
>    (declare (special x) (string x)))
> 
> If we take your idea of allowing this for let* such a special
> declaration could fold parts of your contour. Anyways, I fail to see
> the utility of allowing duplication.

Under Allegro CL

USER(35): (let ((x 1) (x 2)) x)
1
USER(36): (let ((x "foo") (x "bar"))
	    (declare (special x) (string x)))
NIL
From: Dwight Hughes
Subject: Re: Allegro CL groks it. Re: Repeated lambda variables
Date: 
Message-ID: <3697FE12.6310E745@ipa.net>
((lambda (x x) x) 1 2) returns 2 in Corman Common Lisp 1.11 and
Harlequin LispWorks for Windows 4.1 also

-- Dwight

"Christopher R. Barry" wrote:
> 
> ········@poboxes.com writes:
> 
> > I have received a private message about Lxx.x (I use L for
> > lambda, maybe others would find another ASCII character more
> > appropriate), and there has also been a posting.  I could have
> > figured it out myself...  Anyway, as it has been shown, we have:
> >
> >   (Lxx.x)12 === (Lx.(Lx.x))12 -> (Lx.x)2 -> 2
> >
> >   (and also Lxx.x === Lxy.y)
> >
> > which taken literally means that
> >
> >   ((lambda (x x) x) 1 2) should=> 2
> 
> Under Allegro CL
> 
> USER(34): ((lambda (x x) x) 1 2)
> 2
From: Kent M Pitman
Subject: Re: Allegro CL groks it. Re: Repeated lambda variables
Date: 
Message-ID: <sfw3e5jfy6v.fsf@world.std.com>
······@2xtreme.net (Christopher R. Barry) writes:

> >   ((lambda (x x) x) 1 2) should=> 2
> 
> Under Allegro CL
> 
> USER(34): ((lambda (x x) x) 1 2)
> 2
> 
> CMUCL complaigns "Error: Repeated variable in lambda-list: X."

The subject line for this discussion seems misleading to me.  This
form is not defined by CL.  One cannot "grok" something that has no
meaning.  You might have meant to say "Allegro happens, perhaps by
coincidence or luck, not to enter the debugger". ;-)

It looks to me, basd on my understanding, that Allegro's behavior as
you have described it is conforming, but only because when you do
something that is not defined, an implementation is not constrained to
do anything in particular, and therefore pretty much any behavior
would be conforming.

IMO, it is a bad idea to go around checking to see what
implementations do in illegal cases for any other purpose than to
lobby for change in the language.  Also IMO, it is a VERY BAD idea to
think that observing a certain undocumented behavior is a promise that
the undocumented behavior will persist.

Unless you see in the Allegro doc that it INTENDS to return a certain
value in this case, you should avoid doing it.  Partly because the
behavior isn't portable and partly because it might change without
warning even in the same implementation.

Ditto for CMUCL, btw, though it may not be so obvious to you since you
might expect that the error-signalling behavior is somehow more
principled and stable; that is: You should not assume it will signal
an error unless the doc says it will.  Just as nothing prevents
Allegro from signalling an error here, nothing prevents CMUCL from
suddenly and without warning returning either 1 or 2 (or 173, for that
matter) in this case.
From: Marco Antoniotti
Subject: Re: Allegro CL groks it. Re: Repeated lambda variables
Date: 
Message-ID: <lwu2xze2x7.fsf@copernico.parades.rm.cnr.it>
Kent M Pitman <······@world.std.com> writes:

> ······@2xtreme.net (Christopher R. Barry) writes:
> 
> > >   ((lambda (x x) x) 1 2) should=> 2
> > 
> > Under Allegro CL
> > 
> > USER(34): ((lambda (x x) x) 1 2)
> > 2
> > 
> > CMUCL complaigns "Error: Repeated variable in lambda-list: X."
> 
> The subject line for this discussion seems misleading to me.  This
> form is not defined by CL.  One cannot "grok" something that has no
> meaning.  You might have meant to say "Allegro happens, perhaps by
> coincidence or luck, not to enter the debugger". ;-)
> 
> It looks to me, basd on my understanding, that Allegro's behavior as
> you have described it is conforming, but only because when you do
> something that is not defined, an implementation is not constrained to
> do anything in particular, and therefore pretty much any behavior
> would be conforming.
> 
> IMO, it is a bad idea to go around checking to see what
> implementations do in illegal cases for any other purpose than to
> lobby for change in the language.  Also IMO, it is a VERY BAD idea to
> think that observing a certain undocumented behavior is a promise that
> the undocumented behavior will persist.
> 
> Unless you see in the Allegro doc that it INTENDS to return a certain
> value in this case, you should avoid doing it.  Partly because the
> behavior isn't portable and partly because it might change without
> warning even in the same implementation.
> 
> Ditto for CMUCL, btw, though it may not be so obvious to you since you
> might expect that the error-signalling behavior is somehow more
> principled and stable; that is: You should not assume it will signal
> an error unless the doc says it will.  Just as nothing prevents
> Allegro from signalling an error here, nothing prevents CMUCL from
> suddenly and without warning returning either 1 or 2 (or 173, for that
> matter) in this case.
> 

I agree with KMP.  Moreover, I have the following doubt. In CMUCL it
turns out that

* ((lambda (x) (1+ x)) 3)
4

However, this is puzzling to me.  I believe that this is a side effect
of having introduced the LAMBDA macro (therefore punishing me for my
previous comments on it introduction in ANSI CL :) ), but I would
have expected the above form to signal an error.

Any enlightening comments on the matter? Am I missing something from
the specification?

Cheers

Marco

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 10 03 17, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
From: Erik Naggum
Subject: Re: Allegro CL groks it. Re: Repeated lambda variables
Date: 
Message-ID: <3124962600686923@naggum.no>
* Marco Antoniotti <·······@copernico.parades.rm.cnr.it>
| Moreover, I have the following doubt. In CMUCL it turns out that
| 
| * ((lambda (x) (1+ x)) 3)
| 4
| 
| However, this is puzzling to me.

  this has been meaningful since CLtL1 and way before then.  it's called a
  `lambda form' in the standard.  

lambda form n. a form that is a list and that has a first element which is
a lambda expression representing a function to be called on arguments which
are the result of evaluating subsequent elements of the lambda form.

  3.1.2.1.2.4 Lambda Forms reads:

A lambda form is similar to a function form, except that the function name
is replaced by a lambda expression.

A lambda form is equivalent to using funcall of a lexical closure of the
lambda expression on the given arguments.  (In practice, some compilers are
more likely to produce inline code for a lambda form than for an arbitrary
named function that has been declared inline; however, such a difference is
not semantic.)

  http://www.harlequin.com/books/HyperSpec/Body/sym_lambda.html has the
  specification of the symbol LAMBDA.

| Any enlightening comments on the matter? Am I missing something from
| the specification?

  not any more.  :)

#:Erik
From: Kent M Pitman
Subject: Re: Allegro CL groks it. Re: Repeated lambda variables
Date: 
Message-ID: <sfw4spz9i7g.fsf@world.std.com>
Erik Naggum <····@naggum.no> writes:

> * Marco Antoniotti <·······@copernico.parades.rm.cnr.it>
> | Moreover, I have the following doubt. In CMUCL it turns out that
> | * ((lambda (x) (1+ x)) 3)
> | 4
> | However, this is puzzling to me.
> 
>   this has been meaningful since CLtL1 and way before then.  it's called a
>   `lambda form' in the standard.  

Right.  It's called a lambda combination in the traditional literature
but the name didn't seem consistent with "function form" which I was
already using, so I took some liberties with terminology.

But this has been a standard thing ever since Lisp began, and in fact
was an argument against introducing the lambda macro--that it would
confuse people into thinking any form could go in the car of a form
(a la Scheme) if we allowed even one "apparent form" to go there.  
Traditionally, (lambda ...) has been the only compound form which was
permitted to be feval'd (eval'd in the function namespace).  In a 
literal sense, the LAMBDA macro is a translator from the variable namespace
to the funciton namespace because it turns
 (lambda (x) x) => (function (lambda (x) x))
In other words, it requests that the form apparently in the variable
namespace be evaluated in the function namespace.  But it does this
only when you put it in a variable namespace position, as in:
 (funcall (lambda (x) x) 3)
which is equivalent to
 (funcall (function (lambda (x) x)) 3)
because the argument to funcall is evaluated in the variable namespace
and consequently is macroexpanded.  The car of a form is the functional
position and is not evaluated in the variable namespace.  In
 (f x)
the F is evaluated as (function F) not as just F, and consequently
it is also not macroexpanded.  So when you see
 ((lambda (x) x) 3)
you are NOT seeing something equivalent to
 ((function (lambda (x) x)) 3)
because macroexpansion does not occur in the car.  Conceptually, the
motivation for this is that
 ((function f) x)

Symbolics Lisp (and maybe all Lisp Machine Lisp dialects, I don't
remember and am too lazy to look) offers define-lambda-macro which
specifically allows you to define the meaning of a name L in an
expression ((L ...) ...) or (function (L ...)).  Effectively, it's
what I would have called an "fmacro" (a macro on compound forms in the
function namespace) since the convention in history has been to prepend
"f" to things that operate on the function namespace [there having been
many operations like FBOUNDP, FEVAL, FDEFINE, etc. in varying
dialects--FBOUNDP showing itself in Common Lisp].  The purpose of
lambda macros in Symbolics Lisp is to support the definition of
things like Interlisp NLAMBDA, which implicitly quoted all of its
args such that ((nlambda (x y z) (list x y z)) a b c) => (A B C)
In the Lisp Machine's Zetalisp dialect (in which the system is written;
keep in mind Lisp Machines have numerous co-resident dialects in the
same address space), you'd say 
 ((lambda (&quote x y z) (list x y z)) a b c)
and in fact Zetalisp is general enough that you can also do:
 (let ((c 3))
   ((lambda (&quote x y &eval z) (list x y z)) a b c))
 => (A B 3)
Lambda macros could have also been used, though I never saw it done,
to define things like an "identity" function, such that
 (function (eql 17))
might turn into
 (function (lambda (&rest x) (declare (ignore x)) (quote 17)))
That is, they could be general-purpose macros in a different namespace
(not interfering with the meaning of functions in the variable
namespace).  I proposed the introduction of lambda macros into CL,
but no one liked it and it never happened.

See my web-annotated paper 
 http://world.std.com/~pitman/Papers/Special-Forms.html
for why I think &quote and NLAMBDA and related operators (collectively
called FEXPRs in Maclisp parlance) were bad ideas.  They fell really
sharply off into almost total disuse shortly after the paper--though
I've never been sure if it was because of the paper or only because it
was an idea whose time had come and I was just coincidentally writing
about it for the same reason.

Oh, one more thing about LAMBDA.  When I first started using Lisp, there
was a macro capability in Maclisp, but it was virtually unused by the
system.  Many people "invented" LET and the variety of implementations
was fascinating, but it was a common step in learning Lisp that someone
eventually introduced you to LET by assuring you that
 (let ((x 3)) x)
was the same as the "familiar"
 ((lambda (x) x) 3)
It's an interesting commentary on the changing times that not only is
a "lambda combination" or "lambda form" not something that's most
common, but it is so unused that many users now don't even know about
it.  I recall long ago (circa 1978) meeting Al Rich, implementor of
Mulisp, and having him show me his homemade Lisp.  (The story of how
that Lisp got created is an amazing story I'll leave him to tell
himself on another occasion--but let me say I have great respect for
it as an alternate branch in the Lisp tree, even though it's not the
branch I've participated in and tracked.  Don't take my comments here
as disparaging.)  Anyway, because he developed his Lisp in a isolation
of most other influences, he apparently had never noticed the
existence of lambda combinations in his reading, and his Lisp didn't
have it.  Moreover, he had a conditional shorthand that let you write
 ((foo x) y)
which was shorthand for 
 (cond ((foo x) y))
because he didn't think ((anything ...) ...) was ever used and he
thought that was a waste.  I kept writing ((lambda ...) ...) as I was
testing my little toy app in his lisp and it didn't work.  He was as
baffled by what I was writing as I was about the behavior.  It took us
a while to realize the problem, because it was inconceivable to me at
the time that someone would NOT know what a Lambda combination was.
At the time, it was one of the critical and most central things about
Lisp.  What was the point of this story?  I don't know.  Just that
it's funny how expectations change over time, I guess.  Today, Al
Rich's decision to sacrifice lambda combinations in favor of a
conditional shorthand might be defensible as "ground-breaking" for
getting rid of a useless appendage.  (Maybe it always was and I just
didn't see it as such at the time.)  That's why I keep saying over and
over that design decisions are never right or wrong in the
absolute--they only have goodness or badness in a well-understood
context.
From: ········@poboxes.com
Subject: (LET ...) -> ((LAMBDA ...) ...) (Ex: Re: Allegro CL groks it. Re: Repeated lambda variables)
Date: 
Message-ID: <77b1vf$vah$1@nnrp1.dejanews.com>
In article <···············@world.std.com>,
  Kent M Pitman <······@world.std.com> wrote:
(...)
> but it was a common step in learning Lisp that someone
> eventually introduced you to LET by assuring you that
>  (let ((x 3)) x)
> was the same as the "familiar"
>  ((lambda (x) x) 3)

It was a little revelation to me when, about 10 years ago, I was
examining how Sun (i.e. Lucid) Common Lisp 3.0 did various things
and saw that (LET ...) expanded into ((LAMBDA ...) ...).  I knew
about lambda forms, but it had never occurred to me that LET
could be done on top of them.  (This also helped me understand
that CLtL1 rule about the scope of declarations in LET not
including the initialisers.)

Have a nice day or night,
Vassil.


Vassil Nikolov <········@poboxes.com> www.poboxes.com/vnikolov
(You may want to cc your posting to me if I _have_ to see it.)
   LEGEMANVALEMFVTVTVM  (Ancient Roman programmers' adage.)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    
From: Howard R. Stearns
Subject: The first subform of a lambda combination
Date: 
Message-ID: <369BB07C.5730E330@elwood.com>
I always wondered about:

(defun foo (...)
  ...)
(defun (setf foo) (val ...) 
   ...)

(funcall #'foo ...)          ;ok
(funcall #'(setf foo) x ...) ;ok

(funcall 'foo ..)            ;ok
(funcall '(setf foo) x ..)   ;ok

(foo ...)                    ;ok
((setf foo) x ...)    ;Not specifically permitted in ANSI CL

In fact, if I recall correctly, the first subform of a combination must
explicitly be 
of type SYMBOL or (CONS (EQL LAMBDA)).  I might (naively?) have
otherwise assumed that the first subform must be an
EXTENDED-FUNCTION-NAME, or something similar, where
EXTENDED-FUNCTION-NAME (or whatever) is defined in such a way that it
does not preclude special-operators or macro names.
From: Kent M Pitman
Subject: Re: The first subform of a lambda combination
Date: 
Message-ID: <sfwn23oq7rp.fsf@world.std.com>
"Howard R. Stearns" <······@elwood.com> writes:

> I always wondered about:
> 
> (defun foo (...)
>   ...)
> (defun (setf foo) (val ...) 
>    ...)
> 
> (funcall #'foo ...)          ;ok
> (funcall #'(setf foo) x ...) ;ok
> 
> (funcall 'foo ..)            ;ok
> (funcall '(setf foo) x ..)   ;ok
> 
> (foo ...)                    ;ok
> ((setf foo) x ...)    ;Not specifically permitted in ANSI CL
 
I remember discussing this but not the specific positions taken (nor
even my own).  Almost surely someone would have raised the issue that
there was no "current practice" nor "compelling need".  Some others
may also have worried that SETF was already pretty complicated to
understand and that this would only make things worse... I think by
sorta making it look like a schemish (<form> ...) was allowed.  You
see, ((lambda...) ...) had traditionally been allowed, but if it had
to be announced now, I bet it would probably be voted down for same
reason.  But at least it isn't confusing in that its meaning and
syntax is the same in the car of the form as elsewhere, whereas SETF
in the car position would mean something different than elsewhere.  In
the end, it was ad hoc and everyone knew it, and people were probably
so focused on damage control that they didn't look at the bigger
picture.  Just combining speculation with vague fragments of memory
and trying to piece it back together.  Not very reliable from a
historical point of view.  Mostly I agree with what I think you're
saying, though, that this kind of generalization (to allow a setf name
in the car of a form) for the sake of simpler naming is a good idea.
I'll hunt around and see if I can find a specific record of the
issues.

> In fact, if I recall correctly, the first subform of a combination must
> explicitly be 
> of type SYMBOL or (CONS (EQL LAMBDA)).  I might (naively?) have
> otherwise assumed that the first subform must be an
> EXTENDED-FUNCTION-NAME, or something similar, where
> EXTENDED-FUNCTION-NAME (or whatever) is defined in such a way that it
> does not preclude special-operators or macro names.

Yeah...
From: Kent M Pitman
Subject: Re: Repeated lambda variables
Date: 
Message-ID: <sfw4spzfys4.fsf@world.std.com>
Lieven Marchand <···@bewoner.dma.be> writes:

> Kent M Pitman <······@world.std.com> writes:
> [lots of thoughtfull commentary snipped]
> > I wanted the rule to be semantic, not syntactic.)  Anyway,
> > the weird cases, if anyone cares, were things like:
> > 
> >   (let ((x ...) (x ...)) (declare (string x)) ...)
> > 
> > You might think that this should aply to the inner binding,
> > but others felt it should apply to both bindings or that it
> > was at least confusing. Consider specifically:
>
> How does this interact with special?

The question is not relevant unless you, like me, are speaking of
hypothetical universes.  I opened by saying that this is illegal.
All of my discussion was about possible universes that Common Lisp
could have been, but isn't.  I was trying to illustrate how the
language design might have come to the point that it is. 

 
> Consider
> (let ((x ...) (x ...))
>    (declare (special x) (string x)))
> 
> If we take your idea of allowing this for let* such a special
> declaration could fold parts of your contour. Anyways, I fail to see
> the utility of allowing duplication.

I was not making an argument for duplication.  I was surveying the
set of clues that might lead you to one point or the other.  When
designing a language, there are many ways to go.  It's more important
to be internally consistent  than globally correct, since there is
no uniquely determined canonical sense of correct absent a set of 
initial premises.  If you go back and re-read my original note, you'll
see I was talking about things people had suggested that had been
discarded.  My point was that LET* might be given a meaning.  In the
case of LET*,  if you did:
 (let* ((x 'foo) (x (string x)))
   (declare (special x) (string x)) ...)
I'd prefer a semantics in which this meant:
 (let ((x 'foo))
   (let ((x (string x)))
     (declare (special x) (string x))
     ...)))
But not enough people in the committee agreed with me, so it didn't
end up meaning this.