norvig@bansai.uucp (Peter Norvig) (07/12/90)
In several LISPM implementations, we have been able to declare: #'(lambda (x) (declare (sys:downward-function)) (f x y)) to indicate that even though the lambda expression captures the variable y from the environment, it will only be used by functions below, and hence can be stack-allocated, without copying the enviornment. In CLtL2, the declaration DYNAMIC-EXTENT has been added, ostensibly to cover this and other cases. Unfortunately, this means we can no longer use anonymous lambda expressions. I have to say instead: (flet ((f (lambda (x) (declare (dynamic-extent f)) (f x y)))) ... #'f ... ) where the "..." indicate the surrounding environment. Thus, the dynamic-extent declaration does not seem to do the job of sys:downward-function very well. Was this problem discussed when dynamic-extent was adopted?
masinter@parc.xerox.com (Larry Masinter) (07/12/90)
In article <26081@pasteur.Berkeley.EDU> norvig@bansai.uucp (Peter Norvig) writes: > In several LISPM implementations, we have been able to declare: > #'(lambda (x) > (declare (sys:downward-function)) > (f x y)) > to indicate that even though the lambda expression captures the variable y > from the environment, it will only be used by functions below, and hence can > be stack-allocated, without copying the enviornment. > In CLtL2, the declaration DYNAMIC-EXTENT has been added, ostensibly to cover > this and other cases. Unfortunately, this means we can no longer use > anonymous lambda expressions. I have to say instead: > (flet ((f (lambda (x) > (declare (dynamic-extent f)) > (f x y)))) > ... > #'f > ... > ) > where the "..." indicate the surrounding environment. Thus, the > dynamic-extent declaration does not seem to do the job of > sys:downward-function very well. Was this problem discussed > when dynamic-extent was adopted? Well, it was discussed. ================================================================ Begin excerpts (David Moon, replying to Sandra Loosemore...) ================================================================ Date: Fri, 26 May 89 12:22 EDT From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM> Subject: Re: issue DYNAMIC-EXTENT-FUNCTION, version 1 ... Date: Fri, 26 May 89 09:42:51 MDT From: sandra%defun@cs.utah.edu (Sandra J Loosemore) ... I don't know what to do about the related issue of declaring that an anonymous lambda has dynamic extent -- none of the alternatives that have come up so far have much appeal. Anyway, I don't think this problem is as critical, because you could just restructure the program to give the function a name. Do you mean something like: (defmacro dynamic-extent-lambda (lambda-list &body body) `(flet ((dummy-name ,lambda-list ,@body)) (declare (dynamic-extent dummy-name)) #'dummy-name)) The problem with this is that the scope of the dynamic-extent declaration is too small, in fact, so small that this is an erroneous program. That shows something interesting about the Symbolics sys:downward-function declaration: the scope that defines the dynamic extent is larger than the lambda-expression containing the declaration. Implementationally it's the surrounding function definition, semantically it would be enough for it to be the surrounding form. I guess you're going to require that (funcall <foo> (lambda (...) (declare (sys:downward-function)) ...)) be restructured as (flet ((dummy (...) ...)) (declare (dynamic-extent #'dummy)) (funcall <foo> #'dummy)) which is okay except that it's hard to see how to define a macro that gives it back a nice non-obtrusive syntax. Maybe (call-with-dynamic-functions (funcall <foo> #'(lambda (...) ...))) Where the call-with-dynamic-functions macro pulls apart its subform looking for lambda expressions. The macro doesn't need to be in the standard, programming stylists can define it for themselves. It's still more obtrusive than something inside the lambda, though. I think you'd also get the right effect by declaring that all the closed-over variables and functions referenced in the lambda have dynamic extent. I don't think that would mean the same thing. After all, in this example (let ((a <foo>)) (declare (dynamic-extent a)) (<bar> #'(lambda (z) (if (<baz> z) (<frob> a) (<borf> z))))) the dynamic extent declaration for A might mean that by the time the scope of the declaration is exited, something will happen that will make <baz> return false from then on, so A will no longer be referenced, even though the closure that was given as an argument to <bar> will continue to be called. You are correct that the environment of the closure could be discarded, but I don't see how the closure itself could be discarded; it would have to have indefinite extent. So, I don't plan on doing anything about it. I guess that's probably for the best. -- Larry Masinter (masinter@parc.xerox.com) Xerox Palo Alto Research Center (PARC) 3333 Coyote Hill Road; Palo Alto, CA USA 94304 Fax: (415) 494-4333