Path: utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!ukc!edcastle!aiai!jeff From: jeff@aiai.ed.ac.uk (Jeff Dalton) Newsgroups: comp.lang.lisp Subject: Re: PLet Message-ID: <1515@skye.ed.ac.uk> Date: 8 Jan 90 21:02:13 GMT References: <509@cs.columbia.edu> Reply-To: jeff@aiai.UUCP (Jeff Dalton) Organization: AIAI, University of Edinburgh, Scotland Lines: 72 In article <509@cs.columbia.edu> mkamer@cs.columbia.edu (Matthew Kamerman) writes: >As several people pointed out, the macros make assumptions about the >relationship between the Compiler and Run time environments which are >not required in CLtL. The remedy which these people have propoesed >has been using a lexically enclosed function. Stylistically they're >correct, but on most systems lexical closures seem to be inefficiently >implemented (about 30x the cost of FunCall on an Outer Level function). The problem with the lexically enclosed function is that you have to wrap something around the whole function definition, as in (let ((a (compute-a))) (defun use-a () a)) Sometimes you want something more local. For example, you might have a macro that wants to expand into something that involves a once-only evaluation. The macro can't wrap a LET around the function it appears in. I`ve sometimes used the following trick, which is more or less the same as what's at the heart of the PLET macro: (defmacro eval-once (form) `(let ((v ',(gensym))) ;the symbol persists between calls (if (boundp v) (symbol-value v) (set v ,form)))) Instead of saying (plet ((a (compute a))) ...) you'd say (let ((a (eval-once (compute-a)))) ...) Unfortunately, both my macro and PLET have a problem: they create a new symbol each time they're expanded. Since that might be more than once, they don't really cause the evaluation to happen only once. For example, 1> (defun compute-a () (format t "~&Computing a...~%") 10)) compute-a 2> (defun f () (plet ((a (compute-a))) a)) f 3> (f) Computing a... 10 4> (f) Computing a... 10 This is a pain, because it means that there's no way in Common Lisp to get the effect of a static variable. There may be a solution in X3J13 Common Lisp using something called LOAD-TIME-EVAL, which could be used to have something evaluated once, at load time. The result could be an object (a cons cell, say) in which a value could be stored. [It't can't always be the value directly, because it might not be possible to compute the value at load time.] -- Jeff