home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!mcsun!uknet!edcastle!aiai!jeff
- From: jeff@aiai.ed.ac.uk (Jeff Dalton)
- Newsgroups: comp.lang.lisp
- Subject: static, a.k.a. eval-once
- Message-ID: <7399@skye.ed.ac.uk>
- Date: 31 Aug 92 18:46:19 GMT
- Sender: news@aiai.ed.ac.uk
- Organization: AIAI, University of Edinburgh, Scotland
- Lines: 56
-
- About 4 years ago, I wrote an EVAL-ONCE macro. It appears, with
- an explanation below. It has been claimed that my macro isn't
- portable because the behavior of gensyms isn't sufficiently
- restricted when compile and load is involved. What I want to
- know is:
-
- 1. Is there a problem with using GENSYM this way?
-
- 2. Is there a better way to get what I want.
-
- 3. Is there a way that will get the EVAL-ONCE effect in
- interpreted code even in an "expand macros each time"
- implementation? (N.B. There is no correct portable way
- to use *macroexpand-hook* cache macro expansions --
- see page 204 of CLtL II.)
-
- The "better way" will almost certainly involve LOAD-TIME-VALUE.
- But note that simply using LOAD-TIME-VALUE instead of EVAL-ONCE
- is not enough, because it might be that the form can't be evaluated
- at load time. Using LOAD-TIME-VALUE to create a "cell" that
- can be modified to contain the desired value looks like the best
- possibility.
-
- For the interpreted code problem, I can't think of anything better
- than having EVAL-ONCE assume that EQ forms are never logically
- different expressions.
-
- Anyway, here is my old code:
-
- ----------------------------------------------------------------------
- ;;; Oh, let us try this dubious trick...
- ;;; What we want is sort of like 'static'...
- ;;; Some code appears once but is executed again and again.
- ;;; Some value is computed each time the code is executed, but
- ;;; we would like it to be computed once and reused thereafter.
- ;;; (The value can't be computed at compile or load time, perhaps.)
- ;;; Each time this macro appears (modulo re-expansions), it
- ;;; creates a symbol that is ubound the first time the code
- ;;; is executed and has the desired value thereafter.
-
- (defmacro eval-once (form)
- `(let ((v ',(gensym))) ;the symbol persists between calls
- (if (boundp v)
- (symbol-value v)
- (set v ,form))))
-
- #+maybe
- (defmacro eval-once (form)
- (let ((v (gensym)))
- `(locally (declare (special ,v))
- (if (boundp ',v)
- ,v
- (setq ,v ,form)))))
- ----------------------------------------------------------------------
-
- -- jd
-