[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Lexical closures (bug?)



> We were working thru the exercises in Charniak, Riesbeck & McDermot, 
> Artificial Intelligence Programming, and tried the following:
> 
> (defun compose (&rest functions)
>   #'(lambda (x)
>       (do ((fns functions (cdr fns))
> 	   (value x (funcall (car fns) value)))
> 	  ((null fns) value))))
> 
> However, when I try this on my 36xx, with either Genera 7.1 or 7.2, the
> control stack overflows.  In fact if I print the "(car fns)" it is
> apparnet that in each iteration what is being funcalled is not the next
> function, but the entire closure!

The Symbolics treats &rest arguments differently than other types of
arguemnts.  That is, &rest arguments are placed on the stack and
referenced as such.  This works while you are inside of the call to
compose, but once you leave the references still point to the stack
(which is now stale).  What you want to do is put a 

  (let ((copy-of-functions (copy-list functions)))
    ....)

in your code and reference copy-of-functions rather than functions.
This creates a copy of the &rest list which is not on the stack (and
therefore is preserved by the closure).

This feature brought to you courtesy of Symbolics.  (Actually it makes
sense to make this style of funcalling available.  I just don't think
it should be the default.  If Symbolics is going to supersede CLtL,
then it should at least make it a superset (not intersection).  How
about a new keyword: &rest-on-stack ?)
-------
-------