Hello,
I post this message to both c.l.l. and c.l.s. because IMHO it pertains
to both, and would like to receive responses from experts in both
languages.
The following code in Scheme behaves as I would expect:
(define flist '())
(do ((i 1 (+ 1 i)))
((>= i 4))
(set! flist
(cons (lambda (x) (* i x)) flist)))
(map
(lambda (f)
(printf "~a~%" (f 2)))
flist)
It prints "6 4 2". Sorry for the not-too-canonical Scheme, I wrote it
this way to compare with Python and Perl.
In Common Lisp, the same:
(defvar *flist* '())
(dotimes (i 3 t)
(setf *flist*
(cons (lambda (x) (* x i)) *flist*)))
(dolist (f *flist*)
(format t "~a~%" (funcall f 2)))
Prints "6 6 6".
It's curions that Python goes with Common Lisp, while Perl goes with
Scheme here. It's like two camps that treat lexical closures
differently. (See http://stackoverflow.com/questions/233673/lexical-closures-in-python
for the discussion related to Python).
Can you please point me to the resource where this difference is
explained ? I remember from SICP that lexical closures are composed
for each lambda, so the difference in behavior is unclear.
Thanks in advance
Eli
From: Steven E. Harris
Subject: Re: Lexical closures - difference between Common Lisp and Scheme
Date:
Message-ID: <837i7wiwt8.fsf@torus.sehlabs.com>
Eli Bendersky <······@gmail.com> writes:
> Can you please point me to the resource where this difference is
> explained?
I have fond memories of getting schooled here on this subject by Erik
Naggum and a few others in October 2002. See the thread entitled
"Midfunction Recursion", starting with message 17:
,----
| "Re: Midfunction Recursion"
| 24 October 2002
| <················@naggum.no>
| http://groups.google.com/group/comp.lang.lisp/msg/0590de10f975a059
| http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/422226bb18e56cad/0590de10f975a059#0590de10f975a059
`----
--
Steven E. Harris
From: William James
Subject: Re: Lexical closures - difference between Common Lisp and Scheme
Date:
Message-ID: <ge051s0gmv@enews5.newsguy.com>
Steven E. Harris wrote:
> Eli Bendersky <······@gmail.com> writes:
>
> > Can you please point me to the resource where this difference is
> > explained?
>
> I have fond memories of getting schooled here on this subject by Erik
> Naggum and a few others in October 2002. See the thread entitled
> "Midfunction Recursion", starting with message 17:
>
> ,----
> > "Re: Midfunction Recursion"
> > 24 October 2002
> | <················@naggum.no>
> > http://groups.google.com/group/comp.lang.lisp/msg/0590de10f975a059
> >
> > http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/4222
> > 26bb18e56cad/0590de10f975a059#0590de10f975a059
> `----
That thread shows
> (defun uncompress (lst)
> (if (null lst)
> nil
> (let ((elt (car lst))
> (rest (uncompress (cdr lst))))
> (if (consp elt)
> (append (apply #'list-of elt)
> rest)
> (cons elt rest)))))
>
> (defun list-of (n elt)
> (if (zerop n)
> nil
> (cons elt (list-of (- n 1) elt))))
>
> ...
> (uncompress '((3 1) 0 (2 1) 0))
> (1 1 1 0 1 1 0)
Instead of Committee/Cobol Lisp, let's try Ruby.
def uncompress list
list.map{|elt| elt[1,1] * elt[0] rescue elt}.flatten
end
p uncompress( [] )
p uncompress( [3] )
p uncompress( [3,[5,8]] )
p uncompress( [[3,1],0,[2,1],0] )
--- output ---
[]
[3]
[3, 8, 8, 8, 8, 8]
[1, 1, 1, 0, 1, 1, 0]
From: Steven E. Harris
Subject: Re: Lexical closures - difference between Common Lisp and Scheme
Date:
Message-ID: <833aijih3b.fsf@torus.sehlabs.com>
William James <·········@yahoo.com> writes:
> Instead of Committee/Cobol Lisp, let's try Ruby.
Libel and a confession of posting to the wrong group in one sentence?
--
Steven E. Harris
On Oct 25, 11:02 pm, "William James" <·········@yahoo.com> wrote:
> Steven E. Harris wrote:
> > Eli Bendersky <······@gmail.com> writes:
>
> > > Can you please point me to the resource where this difference is
> > > explained?
>
> > I have fond memories of getting schooled here on this subject by Erik
> > Naggum and a few others in October 2002. See the thread entitled
> > "Midfunction Recursion", starting with message 17:
>
> > ,----
> > > "Re: Midfunction Recursion"
> > > 24 October 2002
> > | <················@naggum.no>
> > > http://groups.google.com/group/comp.lang.lisp/msg/0590de10f975a059
>
> > >http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/4222
> > > 26bb18e56cad/0590de10f975a059#0590de10f975a059
> > `----
>
> That thread shows
>
>
>
> > (defun uncompress (lst)
> > (if (null lst)
> > nil
> > (let ((elt (car lst))
> > (rest (uncompress (cdr lst))))
> > (if (consp elt)
> > (append (apply #'list-of elt)
> > rest)
> > (cons elt rest)))))
>
> > (defun list-of (n elt)
> > (if (zerop n)
> > nil
> > (cons elt (list-of (- n 1) elt))))
>
> > ...
> > (uncompress '((3 1) 0 (2 1) 0))
> > (1 1 1 0 1 1 0)
>
> Instead of Committee/Cobol Lisp, let's try Ruby.
>
> def uncompress list
> list.map{|elt| elt[1,1] * elt[0] rescue elt}.flatten
> end
>
> p uncompress( [] )
> p uncompress( [3] )
> p uncompress( [3,[5,8]] )
> p uncompress( [[3,1],0,[2,1],0] )
>
> --- output ---
> []
> [3]
> [3, 8, 8, 8, 8, 8]
> [1, 1, 1, 0, 1, 1, 0]
Instead of pushing your SLDJ onto us grumpy old men, why don't you go
and write a compiler for it? That should keep you busy for some
time. As a hint, you could use Common Lisp as the implementation
language.
Cheers
--
Marco
From: Dimiter "malkia" Stanev
Subject: Re: Lexical closures - difference between Common Lisp and Scheme
Date:
Message-ID: <geb1p4$ko1$1@registered.motzarella.org>
j.oke wrote:
> On 25 Ott, 23:02, "William James" <·········@yahoo.com> wrote:
>> ...
>
> The William tried to fear
> with Ruby (which is like Beer).
>
> The opposer was the Lisp
> which never has to whisp'
> since always had it fine --
> in fact it is like Wine.
>
> Comparing Beer with Wine
> is all but really fine,
> in fact, beer just slows down
> while wine diverts like clown.
>
> (If only he had made
> his starting choice with trait...)
>
> -JO
Brilliant!
In article
<····································@q9g2000hsb.googlegroups.com>,
Eli Bendersky <······@gmail.com> wrote:
> Hello,
>
> I post this message to both c.l.l. and c.l.s. because IMHO it pertains
> to both, and would like to receive responses from experts in both
> languages.
>
> The following code in Scheme behaves as I would expect:
>
> (define flist '())
>
> (do ((i 1 (+ 1 i)))
> ((>= i 4))
> (set! flist
> (cons (lambda (x) (* i x)) flist)))
>
> (map
> (lambda (f)
> (printf "~a~%" (f 2)))
> flist)
>
> It prints "6 4 2". Sorry for the not-too-canonical Scheme, I wrote it
> this way to compare with Python and Perl.
>
> In Common Lisp, the same:
>
> (defvar *flist* '())
>
> (dotimes (i 3 t)
> (setf *flist*
> (cons (lambda (x) (* x i)) *flist*)))
>
> (dolist (f *flist*)
> (format t "~a~%" (funcall f 2)))
>
> Prints "6 6 6".
>
> It's curions that Python goes with Common Lisp, while Perl goes with
> Scheme here. It's like two camps that treat lexical closures
> differently. (See http://stackoverflow.com/questions/233673/lexical-closures-in-python
> for the discussion related to Python).
>
> Can you please point me to the resource where this difference is
> explained ? I remember from SICP that lexical closures are composed
> for each lambda, so the difference in behavior is unclear.
>
> Thanks in advance
> Eli
Often asked. In the iteration there is the variable i. In the
anonymous function you are referencing i. What value should
i have after the iteration is done? 3? NIL? Unbound?
Alternatively one could have a different i on each iteration step
bound to the corresponding value of the iteration step.
In Common Lisp to make sure that the local function
sees a different value for each iteration step, you
have to bind it:
(dotimes (i 3 t)
(setf *flist*
(cons (let ((i i)) (lambda (x) (* x i)))
*flist*)))
--
http://lispm.dyndns.org/
From: Dimiter "malkia" Stanev
Subject: Re: Lexical closures - difference between Common Lisp and Scheme
Date:
Message-ID: <geau5g$2i4$1@registered.motzarella.org>
Thanks, Rainer!
Originally I was baffled why there is such a difference that Eli posted out.
Now it's clear as a day - simple "(let ((i i)))" does the rebinding.
Thank you very much!
Rainer Joswig wrote:
> In article
> <····································@q9g2000hsb.googlegroups.com>,
> Eli Bendersky <······@gmail.com> wrote:
>
>> Hello,
>>
>> I post this message to both c.l.l. and c.l.s. because IMHO it pertains
>> to both, and would like to receive responses from experts in both
>> languages.
>>
>> The following code in Scheme behaves as I would expect:
>>
>> (define flist '())
>>
>> (do ((i 1 (+ 1 i)))
>> ((>= i 4))
>> (set! flist
>> (cons (lambda (x) (* i x)) flist)))
>>
>> (map
>> (lambda (f)
>> (printf "~a~%" (f 2)))
>> flist)
>>
>> It prints "6 4 2". Sorry for the not-too-canonical Scheme, I wrote it
>> this way to compare with Python and Perl.
>>
>> In Common Lisp, the same:
>>
>> (defvar *flist* '())
>>
>> (dotimes (i 3 t)
>> (setf *flist*
>> (cons (lambda (x) (* x i)) *flist*)))
>>
>> (dolist (f *flist*)
>> (format t "~a~%" (funcall f 2)))
>>
>> Prints "6 6 6".
>>
>> It's curions that Python goes with Common Lisp, while Perl goes with
>> Scheme here. It's like two camps that treat lexical closures
>> differently. (See http://stackoverflow.com/questions/233673/lexical-closures-in-python
>> for the discussion related to Python).
>>
>> Can you please point me to the resource where this difference is
>> explained ? I remember from SICP that lexical closures are composed
>> for each lambda, so the difference in behavior is unclear.
>>
>> Thanks in advance
>> Eli
>
> Often asked. In the iteration there is the variable i. In the
> anonymous function you are referencing i. What value should
> i have after the iteration is done? 3? NIL? Unbound?
> Alternatively one could have a different i on each iteration step
> bound to the corresponding value of the iteration step.
>
> In Common Lisp to make sure that the local function
> sees a different value for each iteration step, you
> have to bind it:
>
> (dotimes (i 3 t)
> (setf *flist*
> (cons (let ((i i)) (lambda (x) (* x i)))
> *flist*)))
>
From: Jussi Piitulainen
Subject: Re: Lexical closures - difference between Common Lisp and Scheme
Date:
Message-ID: <qotiqrhdnos.fsf@ruuvi.it.helsinki.fi>
Eli Bendersky writes:
> The following code in Scheme behaves as I would expect:
...
> (do ((i 1 (+ 1 i)))
> ((>= i 4))
> (set! flist
> (cons (lambda (x) (* i x)) flist)))
A new variable is bound to each value, so the behaviour is effectively
like this:
(let ((i 1))
(set! flist (cons (lambda (x) (* i x)) flist)))
(let ((i 2))
(set! flist (cons (lambda (x) (* i x)) flist)))
(let ((i 3))
(set! flist (cons (lambda (x) (* i x)) flist)))
Each of your closures refers to a different i.
> In Common Lisp, the same:
...
> (dotimes (i 3 t)
> (setf *flist*
> (cons (lambda (x) (* x i)) *flist*)))
I believe the loop variable is updated by assignment, so the behaviour
is effectively like this:
(let ((i 1))
(setf *flist* (cons (lambda (* x i)) *flist*))
(setf i 2)
(setf *flist* (cons (lambda (* x i)) *flist*))
(setf i 3)
(setf *flist* (cons (lambda (* x i)) *flist*)))
Each of your closures refers to the same i.
> It's like two camps that treat lexical closures differently.
...
No, the closures are the same. It's the looping constructs that are
different.
I think Common Lisp's `do' is also different from Scheme's and uses
assignment, but if you translate the expansion of Scheme's `do' into
Common Lisp code, you will see that the closures behave the same.
Hm, ok, the macro for `do' in R5RS is a bit tricky, so here's the
essence of the expansion of your loop:
(letrec ((loop (lambda (i)
(if (>= i 4)
'unspecified-value
(begin
(set! flist (lambda (x) (* i x)) flist)
(loop (+ 1 i)))))))
(loop 1))
From: Pascal Bourguignon
Subject: Re: Lexical closures - difference between Common Lisp and Scheme
Date:
Message-ID: <4903058a$0$6108$426a74cc@news.free.fr>
Eli Bendersky wrote:
> Hello,
>
> I post this message to both c.l.l. and c.l.s. because IMHO it pertains
> to both, and would like to receive responses from experts in both
> languages.
>
> The following code in Scheme behaves as I would expect:
>
> (define flist '())
>
> (do ((i 1 (+ 1 i)))
> ((>= i 4))
> (set! flist
> (cons (lambda (x) (* i x)) flist)))
>
> (map
> (lambda (f)
> (printf "~a~%" (f 2)))
> flist)
>
> It prints "6 4 2". Sorry for the not-too-canonical Scheme, I wrote it
> this way to compare with Python and Perl.
>
> In Common Lisp, the same:
>
> (defvar *flist* '())
>
> (dotimes (i 3 t)
> (setf *flist*
> (cons (lambda (x) (* x i)) *flist*)))
You could use do and mapcar like in scheme.
(do ((i 1 (+ 1 i)))
((>= i 4))
(setq *flist*
(cons (lambda (x) (* i x)) *flist*)))
> (dolist (f *flist*)
> (format t "~a~%" (funcall f 2)))
>
> Prints "6 6 6".
(mapcar (lambda (f) (funcall f 2)) *flist*)
--> (8 8 8) ; it could be something else.
But in Common Lisp, it's left up to the implementation whether the
loop variable is bound or assigned in each iteration. If you want to
catch a closure, you have to rebind it yourself, and if you don't, you
will have to write your own loop (because it could be rebound).
> Can you please point me to the resource where this difference is
> explained ?
http://www.lispworks.com/documentation/HyperSpec/Front/Contents.htm
http://schemers.org/Documents/Standards/R5RS/HTML/
> I remember from SICP that lexical closures are composed
> for each lambda, so the difference in behavior is unclear.
This is what you need to do, so the behavior of your code be clear.
--
__Pascal Bourguignon__
http://www.informatimago.com