Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!sun-barr!apple!bionet!agate!eos!shelby!neon!lucid.com!jwz From: jwz@lucid.com (Jamie Zawinski) Newsgroups: comp.lang.clos Subject: Re: Is CLOS Object-Oriented ??? Message-ID: Date: 17 Nov 90 20:05:59 GMT References: <1990Nov15.101847.26285@diku.dk> <3904@s3.ireq.hydro.qc.ca> <39639@ucbvax.BERKELEY.EDU> <1990Nov17.020531.16401@Neon.Stanford.EDU> Sender: jwz@lucid.com Distribution: comp Organization: Lucid, Inc., Menlo Park, CA Lines: 55 In-reply-to: konstan@elmer-fudd.berkeley.edu's message of 17 Nov 90 00:36:18 GMT In article <39639@ucbvax.BERKELEY.EDU> konstan@elmer-fudd.berkeley.edu (Joe Konstan) wrote: > > I agree that slot-value is a useful (if dangerous) feature, but it doesn't > take the place of the above case. One bad (but functional) solution is: > > (eval `(setf (,(slot-to-change button) self) value)) > > Which forces run-time evaluation, but is semantically correct. A simple macro > can hide this detail as follows: > > (defmacro setf-indirect (indirect object new-value) > `(setf (,(eval indirect) ,object) ,new-value)) Well actually I think you meant (defmacro setf-indirect (indirect object new-value) `(eval `(setf (,,indirect ,',object) ,',new-value))) Your example calls EVAL on INDIRECT at macroexpand (compile) time instead of expanding to (eval `(setf (,(slot-to-change button) self) value)). But anyway, this isn't a bad idea just because it runs interpreted, but also because EVAL spawns a new lexical environment; (let ((button (foo)) (self (bar)) (value (baz))) (setf-indirect (slot-to-change button) self value)) which expands to (let ((button (foo)) (self (bar)) (value (baz))) (eval `(setf (,(slot-to-change button) self) value))) will not work because EVAL will not see the lexical bindings of SELF and VALUE. This is why calling EVAL is almost always the wrong thing to do. You could arrange for the list passed to EVAL to contain only constants, as in (eval `(setf (,(slot-to-change button) ',self) ',value)) but in this case, the call to EVAL is little more than a FUNCALL, and could be avoided by clever use of FUNCALL and GET-SETF-METHOD. Under the new standard, there might be an easier way to do this using something like the #'(SETF FOO) syntax; I'm not sure. But all this considered, Phil Stubblefield's solution (funcall (accessor-for-change button) value self) is probably the best, and Flavors really did handle this situation much better than CLOS. -- Jamie