From: Matthias Buelow
Subject: duplicates in lambda-list, let bindings, etc.
Date:
Message-ID: <6dh5bnF2i3k1U1@mid.dfncis.de>
I stumbled across this interesting discrepancy between implementations:
CLisp:
(let ((x 1) (x 2))
x)
==> 2
ECL:
(let ((x 1) (x 2))
x)
==> 1
SBCL:
(let ((x 1) (x 1))
x)
...
; caught ERROR:
; The variable X occurs more than once in the lambda list.
...
It is similar but different for actual lambda lists:
CLisp+ECL:
(funcall (lambda (x x) x) 1 2)
==> 2
SBCL again brings the above error.
Is this unspecified by the standard? SBCL's behaviour seems to make most
sense to me, in terms of catching errors but maybe there's a reason why
there should not be an error.
In article <··············@mid.dfncis.de>,
Matthias Buelow <···@incubus.de> wrote:
> I stumbled across this interesting discrepancy between implementations:
>
> CLisp:
>
> (let ((x 1) (x 2))
> x)
> ==> 2
>
> ECL:
>
> (let ((x 1) (x 2))
> x)
> ==> 1
>
> SBCL:
>
> (let ((x 1) (x 1))
> x)
> ...
> ; caught ERROR:
> ; The variable X occurs more than once in the lambda list.
> ...
>
> It is similar but different for actual lambda lists:
>
> CLisp+ECL:
>
> (funcall (lambda (x x) x) 1 2)
> ==> 2
>
> SBCL again brings the above error.
>
> Is this unspecified by the standard? SBCL's behaviour seems to make most
> sense to me, in terms of catching errors but maybe there's a reason why
> there should not be an error.
I can't find in the HyperSpec if duplicates are allowed or not.
But several implementations give warnings or errors for
duplicate parameters in lambda lists.
Genera:
Command: (defun test (a a) a)
Error: The variable A appears more than once in the lambda list.
LispWorks:
CL-USER 1 > (defun test (a a) a)
TEST
CL-USER 2 > (compile 'test)
;;;*** Warning in TEST: Variable name duplicated in lambda list or LET: A
;;;*** Warning in TEST: A is bound but not referenced
TEST
CL-USER 3 > (defun test (foo) (let ((foo foo) (foo foo)) foo))
TEST
CL-USER 4 > (compile 'test)
;;;*** Warning in TEST: Variable name duplicated in lambda list or LET: FOO
;;;*** Warning in TEST: FOO is bound but not referenced
TEST
--
http://lispm.dyndns.org/
Matthias Buelow <···@incubus.de> writes:
> I stumbled across this interesting discrepancy between implementations:
>
> CLisp:
>
> (let ((x 1) (x 2))
> x)
> ==> 2
>
> ECL:
>
> (let ((x 1) (x 2))
> x)
> ==> 1
>
> SBCL:
>
> (let ((x 1) (x 1))
> x)
> ...
> ; caught ERROR:
> ; The variable X occurs more than once in the lambda list.
> ...
>
> It is similar but different for actual lambda lists:
>
> CLisp+ECL:
>
> (funcall (lambda (x x) x) 1 2)
> ==> 2
>
> SBCL again brings the above error.
>
> Is this unspecified by the standard? SBCL's behaviour seems to make most
> sense to me, in terms of catching errors but maybe there's a reason why
> there should not be an error.
ISTM that lambda and let cannot be compared here.
AFAIR, in the case of LAMBDA the behavior of clisp is what is specified.
Notably when there are initializers, they may refer the previous parameters:
((lambda (x &optional (y x)) ...) parameter-for-x)
<=> (let* ((x parameter-for-x) (y x)) ...)
In the case of LET, since the bindings are made in parallel, both
clisp and ecl are valid, but I don't see anything preventing sbcl to
raise an error.
--
__Pascal Bourguignon__
On Tue, 08 Jul 2008 14:37:10 +0200, Matthias Buelow <···@incubus.de> said:
| [what is supposed to happen with]
| (let ((x 1) (x 2))
| x)
| [and]
| ((lambda (x x) x) 1 2)
CLHS 3.1.1, Introduction to Environments, says that there can be at
most one binding per name per namespace per environment [*], so the
above are not allowed (it is another matter that not all
implementations signal an error, which is not, after all,
specifically required).
3.1.3, Lambda Expressions, establishes that there is a single
environment for a lambda expression. I don't think there is an
equally explicit specification that LET establishes a single
environment, but I believe it is quite reasonable to presume that if
that hadn't been the case, there would have been an explicit
specification to the contrary. (And (LET ((var value) ...) . body)
is practically the same as ((LAMBDA (var ...) . body) value ...).)
By the way, this is a non-issue with lambda terms, at least with the
usual syntax rules, where {\lambda}xy.T is nothing but
{\lambda}x.{\lambda}y.T and thus obviously there is nothing special
about {\lambda}xx.T.
_________
[*] Very pedantically speaking, is ((lambda (x x) x) 'a 'a) legal?
---Vassil.
--
Peius melius est. ---Ricardus Gabriel.