Kent M Pitman <pitman@world.std.com> wrote:
+---------------
| This relates to my beef about tail recursion in Scheme, which I think
| is a fine new way of looking at an old idea that offers interesting
| leverage, but that should not be thought of as a replacement for
| the old idea of iterating, which has its own power in terms of being
| a simpler formulation for the set of simple cases where the more
| complex formulation is not needed.
+---------------
[And at the risk of getting flamed for it,] I'll say again that one of
the additional dangers in talking about tail-recursion as "the Scheme
way of iterating" is that the storage & variable-binding behaviors of
Scheme "iteration" -- as it is conventionally coded [with the state held
in bound variables in a "do" or "(let loop...)" or explicit self-tail-call
parameters] -- and Common Lisp iterative constructs are not the same,
either. For example, in Scheme's "do" each trip around the loop binds
the variables to *fresh* locations, which are then initialized with
the "step" values, while in Common Lisp's "do" the *same* bindings are
*assigned* to ("as with psetq", sez the HyperSpec) with the "step" values.
Not only can this lead to very different allocation patterns and garbage
collector behavior (as I think I mentioned before in this thread), but
also to very different results!! Consider this somewhat contrived example
[actually run on several Schemes and on CLISP, just to be sure! ;-} ]:
=== Scheme === === Common Lisp ===
> (define (foo) > (defun foo ()
(do ((i 0 (+ 1 i)) (do ((i 0 (+ 1 i))
(j (lambda () 'first) (j (lambda () 'first)
(lambda () i)) (lambda () i))
(k '() (cons j k))) (k '() (cons j k)))
((> i 3) (reverse k)))) ((> i 3) (reverse k))))
FOO
> (map (lambda (x) (x)) (foo)) > (mapcar #'funcall (foo))
(first 0 1 2) (FIRST 4 4 4)
> >
The "foo"s are IDENTICAL (well, define/defun syntax), yet the results
certainly aren't!
-Rob
p.s. You *can*, of course, write a "do" loop in Scheme that gives CL-like
semantics for this example, but you have to go to more trouble:
> (define (foo2)
(let ((shared-i 'ignored))
(do ((i 0 (+ 1 i))
(j (lambda () 'first)
(lambda () shared-i))
(k '() (cons j k)))
((> i 3) (set! shared-i i) (reverse k))
(set! shared-i i))))
> (map (lambda (x) (x)) (foo2))
(first 4 4 4)
>
[And, yes, I know, the second "set!" is not necessary... in *this* example...]
-----
Rob Warnock, 8L-855 rpw3@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