From: rif
Subject: Making symbols in a macro
Date: 
Message-ID: <wj0r82yn9kw.fsf@five-percent-nation.mit.edu>
Say I have a class foo, with slots a, b, and c.  I'd like to be able
to write a macro with-foos that automatically gave me variables that
accessed the slots.  So for instance, I'd like

(with-foos (f1 f2) (+ f1-a f2-b))

to yield the same result as

(+ (a f1) (b f2))

(where the appropriate slot-accessors have been defined).

(Of course, my code's also going to expand into the appropriate type
declarations so I don't have to write them everywhere, which is the
real reason I want to do this.)

But I'm not sure how.  I tried using make-symbol, but I end up with a
symbol like #:|f1-a| in my macroexpansion, which is not what I want.

Any thoughts?  Is a symbol not what I want at all?

Cheers,

rif

From: Erann Gat
Subject: Re: Making symbols in a macro
Date: 
Message-ID: <gat-0209031500480001@k-137-79-50-101.jpl.nasa.gov>
In article <···············@five-percent-nation.mit.edu>, rif
<···@mit.edu> wrote:

> Say I have a class foo, with slots a, b, and c.  I'd like to be able
> to write a macro with-foos that automatically gave me variables that
> accessed the slots.  So for instance, I'd like
> 
> (with-foos (f1 f2) (+ f1-a f2-b))
> 
> to yield the same result as
> 
> (+ (a f1) (b f2))
> 
> (where the appropriate slot-accessors have been defined).
> 
> (Of course, my code's also going to expand into the appropriate type
> declarations so I don't have to write them everywhere, which is the
> real reason I want to do this.)
> 
> But I'm not sure how.  I tried using make-symbol, but I end up with a
> symbol like #:|f1-a| in my macroexpansion, which is not what I want.
> 
> Any thoughts?  Is a symbol not what I want at all?

You probably want WITH-SLOTS.

http://www-2.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/mac_with-slots.html

E.
From: Kent M Pitman
Subject: Re: Making symbols in a macro
Date: 
Message-ID: <sfwznhmn96t.fsf@shell01.TheWorld.com>
rif <···@mit.edu> writes:

> Say I have a class foo, with slots a, b, and c.  I'd like to be able
> to write a macro with-foos that automatically gave me variables that
> accessed the slots.  So for instance, I'd like
> 
> (with-foos (f1 f2) (+ f1-a f2-b))
> 
> to yield the same result as
> 
> (+ (a f1) (b f2))
> 
> (where the appropriate slot-accessors have been defined).
> 
> (Of course, my code's also going to expand into the appropriate type
> declarations so I don't have to write them everywhere, which is the
> real reason I want to do this.)
> 
> But I'm not sure how.  I tried using make-symbol, but I end up with a
> symbol like #:|f1-a| in my macroexpansion, which is not what I want.

1. Make uppercase symbol names.  Except with special syntactic quoting by 
   backslash (as in \a) or vertical bar (as in |a|), all case seen by the
   reader is internally uppercase.  The |f1-a| is reminding you that you've
   used lowercase, which is not what you want.
 
2. Use INTERN, not MAKE-SYMBOL.  INTERN is for symbols you want to be able
   to touch anew when their name is mentioned.  MAKE-SYMBOL is for unique
   symbols distinct from any the reader might make.  Since your goal is to
   tie the symbols in the rest of the form to the symbols you're making, you
   don't want unique symbols!

> Any thoughts?  Is a symbol not what I want at all?

It is.

A secondary style question is whether this is a good idea.
I'm not so sure it is. 

Incidentally, since you'll generate a great many symbols the value of which
you might not use, you'll want to declare all of the symbols you bind as
IGNORABLE if you make them with LET... 

The fact that you're probably using SYMBOL-MACROLET or WITH-ACCESSORS or
some such internally instead of LET speaks to why this might not be a good
idea.  You're certainly not saving any computation by donig this.  Indeed,
you might be donig a good deal more computation than you need.  That is,
 if (+ foo-a foo-a) => (+ (a foo) (a foo)) 
then you're computing (a foo) twice.  If the body is large and has many
references, you may be computing it a lot of times.
From: Kaz Kylheku
Subject: Re: Making symbols in a macro
Date: 
Message-ID: <cf333042.0309021749.41a80ac8@posting.google.com>
rif <···@mit.edu> wrote in message news:<···············@five-percent-nation.mit.edu>...
> Say I have a class foo, with slots a, b, and c.  I'd like to be able
> to write a macro with-foos that automatically gave me variables that
> accessed the slots.  So for instance, I'd like
> 
> (with-foos (f1 f2) (+ f1-a f2-b))

This can't work because WITH-FOOS hasn't been given an argument to
tell it what object to use. In Lisp you don't have a ``self'' or
``this'' variable.

There is a standard macro WITH-SLOTS:

  (with-slots (f1 f2) object-expr
     ...)

This evaluates the expression OBJECT-EXPR, which is expected to yield
an object with slots F1 and F2. Symbol macros are created which, in
the lexical contour indicates by ... behave like variables bound to
the slots of the object computed by that expression.

Renaming is possible as well to combat ambiguitities:

  (defmethod draw-segment ((p0 point) (p1 point))
    (with-slots ((x0 x) (y0 y)) p0
      (with-slots ((x1 x) (y1 y)) p1
        (draw-line x0 y0 x1 y1))))

> to yield the same result as
> 
> (+ (a f1) (b f2))
> 
> (where the appropriate slot-accessors have been defined).

To make your own WITH-SLOTS-like macros, the underlying building block
is SYMBOL-MACROLET. I have my own macro that is like WITH-SLOTS but
which shallowly binds the symbols to *expressions* that refer to
slots, rather than to the slots themselves. This is a subtle
difference which lets you do things like:

  (with-slots (a b) obj
    (dolist (obj obj-list)
      (do-something-with a b)))

Not a terribly useful example, but it shows you how when the variable
OBJ is rebound to the objects in the list, the A and B bindings follow
the change in reference; A expand to the expressions (SLOT-VALUE OBJ
'A), so that the expression OBJ is re-evaluated each time A is
accessed. The standard WITH-SLOTS macro avoids this reevaluation; the
bindings are made permanent with a gensym trick or whatever.

> (Of course, my code's also going to expand into the appropriate type
> declarations so I don't have to write them everywhere, which is the
> real reason I want to do this.)
> 
> But I'm not sure how.  I tried using make-symbol, but I end up with a
> symbol like #:|f1-a| in my macroexpansion, which is not what I want.
> 
> Any thoughts?  Is a symbol not what I want at all?

You want a symbol macro:

   (let ((my-object (make-instance 'my-class)))
     (symbol-macrolet ((a (slot-value my-object 'a))
                       (b (slot-value my-object 'b))
       ...)))
From: rif
Subject: Re: Making symbols in a macro
Date: 
Message-ID: <wj0oey2otyi.fsf@five-percent-nation.mit.edu>
OK, thanks to everyone for all the great responses so far.  I've been
told how to do what I asked, given explanations of why I don't really
want to do it, and given suggestions for what to do instead.  Thanks
all!

Cheers,

rif
From: james anderson
Subject: Re: Making symbols in a macro
Date: 
Message-ID: <3F551E0B.FD08D525@setf.de>
rif wrote:
> 
> (Of course, my code's also going to expand into the appropriate type
> declarations so I don't have to write them everywhere, which is the
> real reason I want to do this.)

? are implementations less likely to observe the type declarations on the
accessors than on the variables?

> 
> But I'm not sure how.  I tried using make-symbol, but I end up with a
> symbol like #:|f1-a| in my macroexpansion, which is not what I want.
>