Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!bloom-beacon!husc6!yale!Krulwich-Bruce From: Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) Newsgroups: comp.lang.lisp Subject: Re: Self-referencing Closures Message-ID: <52880@yale-celray.yale.UUCP> Date: 7 Mar 89 02:01:13 GMT References: <6859@phoenix.Princeton.EDU> Sender: root@yale.UUCP Reply-To: Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) Organization: Computer Science, Yale University, New Haven, CT 06520-2158 Lines: 51 In-reply-to: eliot@phoenix.Princeton.EDU (Eliot Handelman) In article <6859@phoenix.Princeton.EDU>, eliot@phoenix (Eliot Handelman) writes: >The situation is this: a process, represented as a closure, spawns a >child, another closure. The parent then runs the child, and when the >child finishes it returns to the parent. I am doing this using continuations, >that is, the child is passed the parent closure which it then funcalls >when it has finished. So the parent has to be able to pass itself to the >child. > >(defun make-closure () > (let (-self-) > (setq -self- #'(lambda () > )))) > >Does this seem like a particularly bad idea? Is there some important reason >why I would not want to do this? Is there some reason why I wouldn't >want to use SETQ? Can this be done more elegantly? All criticism welcome. There is no need to use the LET/SETQ combination because the LABELS construct (CLtL p113) exists exactly for this reason. LABELS allows definition of local functions that can reference themselves and each other recursively. The above code can be written as: (defun make-closure () (labels ((-self- () )) -self-)) If you really tend towards the boroque you can use "Church's Y operator" which is defined in Scheme using: (define (y f) ((lambda (g) (lambda (h) ((f (g g)) h))) (lambda (g) (lambda (h) ((f (g g)) h))))) (the CL version would have alot of FUNCALL and #'s thrown in) to make recursive closures without using "explicit" recursion constructs. Using the above definition you can make a closure to recursively compute the factorial function by calling: (y (lambda (fn) (lambda (x) (if (zerop x) 1 (* x (fn (- x 1))))))) Anyway, LABELS is what you want. Bruce Krulwich