From: Gordon Buxton
Subject: local macro definitions
Date: 
Message-ID: <4133@inca.comlab.ox.ac.uk>
Sorry if this is a naive question, but you all seem pretty
knowledgeable:

I'm trying to write a function for accessing data stored in slots of
frames.  The problem is that if no value is available from that slot,
I want to go and execute a bit of user code attached to that slot.
The basic function that I am using looks like this:

(val '<frame-name> '<slot-name>)

At the moment, the user code attached to the slot gets called with the
symbol 'self' bound to the value of <frame-name>.  This lets the user
code get at values from other slots in the same frame by inserting

... (val self '<another-slot-name>) ...

as part of the code.  This is pretty horrible.  What I would really
like to do is to let the user refer to the other slot names in the
frame as if they were locally bound variables: eg. you could do:

(+ <slot-1> <slot-2>)

as a valid part of the code.

Does anyone have any great ideas on doing this?  The following methods
I have thought of, but are either no good or I don't know how to
implement them:

1. A list of all of the slots present in a frame is available; the
user code calling sequence could bind each slot name to the value of
the (val ..) function called for that slot.

	-- Inefficient to say the least.  In fact it gets more hideous
	   the more you think about it.

2. Do some parsing on the user code, to work out which slots are
needed, and just go and get them before executing the code.

	-- Doesn't strike me as a good idea.

3. Bind each of the slot names to a macro (macrolet ... ?) that then
gets expanded to (val self '<slot-name>) upon execution.

-- This is the one I like best, but there are two problems:
   a) The user-code function call is already constructed using the
      backquote - I'd have to expand macros within this.
   b) I don't know how to do it, or if it is possible

Your help would be greatly appreciated on this.

Thanks

Gordon

--------------------------
······@robots.oxford.ac.uk
Gordon Buxton
Pembroke College
Oxford OX1 1DW
--------------------------

From: Barry Margolin
Subject: Re: local macro definitions
Date: 
Message-ID: <151idvINN6mn@early-bird.think.com>
In article <····@inca.comlab.ox.ac.uk> ······@robots.oxford.ac.uk (Gordon Buxton) writes:
>3. Bind each of the slot names to a macro (macrolet ... ?) that then
>gets expanded to (val self '<slot-name>) upon execution.

If I understand you, this seems like the right thing.  The name of the
special form is SYMBOL-MACROLET, and it was invented for use by CLOS for
pretty much the same thing you're doing with your frames (e.g.
WITH-ACCESSORS and WITH-SLOTS expand into SYMBOL-MACROLET forms).

>-- This is the one I like best, but there are two problems:
>   a) The user-code function call is already constructed using the
>      backquote - I'd have to expand macros within this.

This shouldn't be necessary.  It's hard to say for sure, but the right
macro and symbol-macro expansions should all occur automatically.

>   b) I don't know how to do it, or if it is possible

(symbol-macrolet ((<slot-1> (val self '<slot-1>))
		  (<slot-2> (val self '<slot-2>))
		  ...)
  <code that references <slot-N> as variables>)

See CLtL2 for more details.
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar
From: Len Charest
Subject: Re: local macro definitions
Date: 
Message-ID: <1992Jul27.220158.28453@jpl-devvax.jpl.nasa.gov>
In article <····@inca.comlab.ox.ac.uk>, ······@robots.oxford.ac.uk (Gordon Buxton) writes:
|>  What I would really
|> like to do is to let the user refer to the other slot names in the
|> frame as if they were locally bound variables:

All of the approaches suggested here imply that the list of frame slots
is available at compile-time (really macroexpansion-time). Is this
truly the case?

|> 
|> 1. A list of all of the slots present in a frame is available; the
|> user code calling sequence could bind each slot name to the value of
|> the (val ..) function called for that slot.
|> 
|> 	-- Inefficient to say the least.  In fact it gets more hideous
|> 	   the more you think about it.

Why does is this intrinsically inefficent? You could hide the binding
mechanism from the user code by wrapping the following code fragment
around the user code:

(let ((slots <list of frame slots>))
  (flet ((val-in-self (slot)
	   (val self slot))) 
    ;;dynamically bind the slot names to values 
    (progv slots (mapcar #'val-in-self slots)
      ...<user code here>...
      )))

The only (potential) drawback I can see is that calling VAL on each of
the slots of the frame SELF is going to force execution of the user
code in some cases (e.g, 'unbound' slots as you mentioned), possibly
resulting in infinite recursion.

|> 2. Do some parsing on the user code, to work out which slots are
|> needed, and just go and get them before executing the code.
|> 
|> 	-- Doesn't strike me as a good idea.

This is a great idea! If you are certain that a slot name (i.e.,
symbol) is really just a symbolic reference to the slot's value in this
context then you could re-write the body of the user code so that every
reference to a slot name is replaced by the corresponding (eq) value.
For example

(flet ((insert-value (slot body)
         (nsubst (val self slot) slot body :test #'eq)))
  (let ((body (copy-tree <user code>)))
    (loop for slot in <list of frame slots>
          do (setq body (insert-value slot body)))
    body))
          
You might even choose to 'optimize' other parts of the user code at
this point.

|> 3. Bind each of the slot names to a macro (macrolet ... ?) that then
|> gets expanded to (val self '<slot-name>) upon execution.

As barmar has already pointed out, the form to use is SYMBOL-MACROLET.
..................................................
                                  Len Charest, Jr.
                 JPL Artificial Intelligence Group
                          ·······@aig.jpl.nasa.gov