[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Using Macros in Lisp



> > Don't write a macro UNLESS:
> > B: It will be used in LOTS of places in your code and will save you
> >    LOTS of typing and make the code a LOT clearer.  (e.g. (with-open-file..))
>
>I would say if it makes your code a lot clearer then do it regardless
>of whether or not it also saves you typing or is used in lots of
>places.  Anything that makes your code clearer is a win.
Yes, I overstated it.
Of course, in LISP any piece of code that you write twice is written LOTS.
:-)

> > C: You NEED the arguments to be unevaluated so you can process them BEFORE
> >    you do the function.
> > (e.g.  (defmacro frame (name) `(find-frame ',name)))
>    
>What about this example requires it to be a macro?  Is it so you
>can type (FRAME DOG) rather than (FIND-FRAME 'DOG)?  This is not
>convincing to me.
This was a stupid little example. (like the ones I complained about :-)).
But for something like (defclass...), you can see where inluding all the
quotes and conversion from class-names to the actual class objects and
wrapping the init forms in a lambda is a case for macros.  I had assumed
that this one would remind you of the earlier example.
> > D:  You are going to save a LOT of run-time cycles by computing something.
> > (e.g.  (defmacro slot-value (type object slot-name)
> >            ;...hairy computation of integer result deleted...
> >           `(svref (node-vector ,object) ,result))
> > )
>    
>Mumble.  Yes, although the cases where you will have enough
>information to do that at compile time are very few.  If I really
>want to do something like that use `#.' (eval at read time).
Again, this is meant to be something like a definition of a PCL-like
reference.  I am currently using a home-built object system that does
something like this.  In almost all cases, I do know the type of the object
(or at least the ancestor in which I am interested), so I *do* have enough
information at compile-time to calculate that I want (for example) offset
42 in the node's vector, which is a structure slot.  I also handle
load-on-demand for the object in question in with the hairy computation.

> > E:  You need to be able to setf some portion of a structure.
> > (e.g. (setf (slot-value person *fred* name) "Fred"))
>
>I'm not sure what this is doing.  Will slot-value expand into a
>structure accessor, so that the and the setf form expands into this:
>
>  (setf (person-name *fred*) "Fred")
>    
>This is also a very limited situation because it will only work when
>you know the slot name and type of the object at compile time.  If
In your very own example, you make it clear that you DO know person and
name, which is all I need.  Perhaps I should have specified that *fred* may
actually be a *professor* which is an *employee* which is a *person*.  I
may not know his exact type, but I KNOW he/she/it is a person, which has a
name.

>that's the case then there is very little difference between
>
>  (slot-value person *fred* name)
>
>and
>
>  (person-name *fred*)
Nope.  See, *fred* is not a straight structure.  It is a structure with a
type and a vector and with that information I can calculate exactly where
in the vector to set the new value.  I also have to run the if-sets (if
any), time-stamp the node as changed, and maybe even do some type-checking.
 To do all this, one has to write a read macro and a write macro and use
define-setf-method rather than defsetf.  Fun.  :-)

"TANSTAAFL" Rich lynch@aristotle.ils.nwu.edu