Misunderstanding about closures
Alexander Schmolck
a.schmolck at gmx.net
Sat Jun 12 17:50:35 EDT 2004
Jacek Generowicz <jacek.generowicz at cern.ch> writes:
> Alexander Schmolck <a.schmolck at gmx.net> writes:
>
>> Not quite. In fact in the language that more or less started it all,
>> scheme, the standard iteration construct 'do' does indeed introduce
>> a *new binding* on each iteration.
>
> Yes, but this is a consequence of Scheme faking iteration with
> recursion.
Why "faking"? How is this CL-style do below inferior to the real thing (apart
from the fact that it's possibly inelgant or broken because it's quickly
hacked together by someone of limited competence as a scheme programmer:)?
;; cl-style do (with mandatory step clause, to make the code a bit more
;; compact)
(define-syntax cl-style-do
(syntax-rules ()
;; this...
[(cl-style-do ((var init step) ...) (end-test result ...) body ...)
;; ... gets rewritten as
(let ((var init) ...) ; normal let; similar to var = init; ...
(let loop () ; named let: like def loop(): ...; loop()
(if end-test
(begin
(if #f #f) ; trick to get void return value if no result form
result ...) ; is given
(begin body ...
(set! var step) ...
(loop)))))]
))
;; for comparison, this is a (again slightly simplified) scheme style do
(define-syntax scheme-style-do
(syntax-rules ()
;; this...
[(scheme-style-do ((var init step) ...) (end-test result ...) body ...)
;; ... gets rewritten as
(let loop ((var init) ...) ; like def loop(var...): ...; loop(init...)
(if end-test
(begin
(if #f #f)
result ...)
(begin body ...
(loop step ...))))]
))
Recycling the contorted pythonesque scheme example I posted earlier:
(define l '()) ; an empty list
(cl-style-do ((x 0 (+ 1 x))) ; start x with 0, then add 1 at each step
((= x 10)) ; stop when x is 10
(set! l (cons (lambda () x) l))) ; add a new function closing over x to
; the *front* of l
(set! l (reverse l)) ; since we added to the front we
; have to reverse l
((list-ref l 3)) ; get list element 3 and execute it
=> 10 (same as in CL; not 3 as with standard do)
>> Common Lisp OTOH doesn't -- like python:
>
> If you used recursion-based iteration constructs in either of these
> languages, the same would happen.
>
> Future Googlers please refer to:
>
> http://www.google.com/groups?as_umsgid=tyfsmgtbewl.fsf%40lxplus030.cern.ch
Again you seem to imply that somehow scheme does something inappropriate
and/or is somehow limiting compared to CL/python style iteration -- whereas
AFAICT the exact opposite applies.
I can't see how the new bindings that scheme's do introduces on each iteration
step matter unless you create a closure in the body of the do loop and in that
case chances are scheme's behavior is *precisely* what you want. And if, for
some (obscure ?) reason, CL style do is what you need then I think you can
trivially implement it as above.
OTOH, if you want scheme style tail recursion (which makes it feasible to
express some problems significantly simpler and quite a few more lucidly than
if you had to use plain iteration) in (standard) CL or python you're pretty
screwed -- you can to some extent fake it in CL, but even that requires a lot
of work. For python you'd have to write a compiler to standard python (or
bytecode).
'as
More information about the Python-list
mailing list