From: Thomas Elam
Subject: Request for help constructing a simple macro
Date: 
Message-ID: <1172775993.204461.9570@k78g2000cwa.googlegroups.com>
I still don't understand macros very well. (I have read Graham's ANSI
Common Lisp and understood the examples, but the ideas didn't sink
deep into my mind.) I can write very simple macros. I looked around
for awhile and can't find anything like what I want, though I am sure
there are lots of examples.

I just want something that would work like this:

(pop-fields list a b c d)
=> (setf a (pop list))
     (setf b (pop list))
     (setf c (pop list))
     (setf d (pop list))

Any help would be greatly appreciated.

From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172780147.527183.165980@30g2000cwc.googlegroups.com>
On Mar 2, 12:06 am, "Thomas Elam" <·······@gmail.com> wrote:
> I still don't understand macros very well. (I have read Graham's ANSI
> Common Lisp and understood the examples, but the ideas didn't sink
> deep into my mind.) I can write very simple macros. I looked around
> for awhile and can't find anything like what I want, though I am sure
> there are lots of examples.
>
> I just want something that would work like this:
>
> (pop-fields list a b c d)
> => (setf a (pop list))
>      (setf b (pop list))
>      (setf c (pop list))
>      (setf d (pop list))
>
> Any help would be greatly appreciated.

I am going to read and study Pascal's very succinct post
http://groups.google.co.in/group/comp.lang.lisp/msg/aced98a13ca36b45?hl=en&
From: Joel Wilsson
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172780304.928363.160170@t69g2000cwt.googlegroups.com>
On Mar 1, 8:06 pm, "Thomas Elam" <·······@gmail.com> wrote:
> (pop-fields list a b c d)
> => (setf a (pop list))
>      (setf b (pop list))
>      (setf c (pop list))
>      (setf d (pop list))
>
> Any help would be greatly appreciated.

(defmacro pop-fields (place-to-pop &rest places-to-set)
  `(progn ,@(loop for place in places-to-set
               collect `(setf ,place (pop ,place-to-pop)))))

CL-USER> (macroexpand-1 '(pop-fields list a b c d))
(PROGN
 (SETF A (POP LIST))
 (SETF B (POP LIST))
 (SETF C (POP LIST))
 (SETF D (POP LIST)))
T

You have to ask about the specifics for me to be able to help you
more,
since you say you understand the examples in ANSI Common Lisp and this
macro here isn't more complicated than those, I think.

Regards,
  Joel
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172780735.292365.177720@t69g2000cwt.googlegroups.com>
On Mar 2, 1:18 am, "Joel Wilsson" <············@gmail.com> wrote:
> On Mar 1, 8:06 pm, "Thomas Elam" <·······@gmail.com> wrote:
>
> > (pop-fields list a b c d)
> > => (setf a (pop list))
> >      (setf b (pop list))
> >      (setf c (pop list))
> >      (setf d (pop list))
>
> > Any help would be greatly appreciated.
>
> (defmacro pop-fields (place-to-pop &rest places-to-set)
>   `(progn ,@(loop for place in places-to-set
>                collect `(setf ,place (pop ,place-to-pop)))))
>
> CL-USER> (macroexpand-1 '(pop-fields list a b c d))
> (PROGN
>  (SETF A (POP LIST))
>  (SETF B (POP LIST))
>  (SETF C (POP LIST))
>  (SETF D (POP LIST)))
> T
>
> You have to ask about the specifics for me to be able to help you
> more,
> since you say you understand the examples in ANSI Common Lisp and this
> macro here isn't more complicated than those, I think.
>
> Regards,
>   Joel


Joel, thanks. I am going to sound stupid for what I'm about to say,
but I understood Graham's examples only for a short time after reading
them. After a year or two, I forgot most of what I learned about
macros. I *always* had a lot of trouble writing my own macros. I will
study your code, which I think I'll be able to understand after I get
some sleep.
From: Tayssir John Gabbour
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172783762.699417.219400@v33g2000cwv.googlegroups.com>
On Mar 1, 9:25 pm, "Thomas Elam" <·······@gmail.com> wrote:
> Joel, thanks. I am going to sound stupid for what I'm about to say,
> but I understood Graham's examples only for a short time after reading
> them. After a year or two, I forgot most of what I learned about
> macros. I *always* had a lot of trouble writing my own macros. I will
> study your code, which I think I'll be able to understand after I get
> some sleep.

That's no doubt common. Perhaps you'll find the explanation of macros
in _Practical Common Lisp_ more intuitive... PCL is likely the most
popular intro to Lisp.
<http://www.gigamonkeys.com/book/macros-defining-your-own.html>

Tayssir
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172816500.062683.138780@z35g2000cwz.googlegroups.com>
On Mar 2, 2:16 am, "Tayssir John Gabbour"
<············@googlemail.com> wrote:
> On Mar 1, 9:25 pm, "Thomas Elam" <·······@gmail.com> wrote:
>
> > Joel, thanks. I am going to sound stupid for what I'm about to say,
> > but I understood Graham's examples only for a short time after reading
> > them. After a year or two, I forgot most of what I learned about
> > macros. I *always* had a lot of trouble writing my own macros. I will
> > study your code, which I think I'll be able to understand after I get
> > some sleep.
>
> That's no doubt common. Perhaps you'll find the explanation of macros
> in _Practical Common Lisp_ more intuitive... PCL is likely the most
> popular intro to Lisp.
> <http://www.gigamonkeys.com/book/macros-defining-your-own.html>
>
> Tayssir


I did read at least some of that section. I would love to find a good
book midway in tone between PCL and ANSI CL. I think it will take me
at least 2 or 3 hours on one of my better days to grok this stuff
well. I think that I will finally get it deeply if I can understand
the order of evaluation (or nonevaluation) and the (nonmacro-related)
quoting and quasiquoting. I think I fully appreciate *what* macros can
do, but not how. I think I even don't understand symbols very well,
coming from a C background as I am. An object that is a symbol? It's
hard for me to get used to. It's not even a string. Wow. Different.
But I love it.
From: Dan Bensen
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <es8hg5$4ah$1@wildfire.prairienet.org>
Thomas Elam wrote:
> do, but not how. I think I even don't understand symbols very well,
> coming from a C background as I am. An object that is a symbol? It's
> hard for me to get used to. It's not even a string. Wow. Different.

I had trouble with that too.  The word "symbol" is an unfortunate choice 
as far as the beginner is concerned.  Experienced Lispers understand 
that what Lisp calls a "symbol" is a type of object, not a name or 
character string.  A symbol (i.e., an object) is created whenever a 
variable is introduced into the program, and the symbol has a field 
called the "print name" that gets set to the name of the variable.
Since variables and functions have separate namespaces, the symbol also 
has a variable field and a function field to keep track of the variables 
and functions that have the same name as the print name of the symbol.

-- 
Dan
www.prairienet.org/~dsb
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172825533.659360.138760@8g2000cwh.googlegroups.com>
On Mar 2, 7:55 am, Dan Bensen <··········@cyberspace.net> wrote:
> Thomas Elam wrote:
> > do, but not how. I think I even don't understand symbols very well,
> > coming from a C background as I am. An object that is a symbol? It's
> > hard for me to get used to. It's not even a string. Wow. Different.
>
> I had trouble with that too.  The word "symbol" is an unfortunate choice
> as far as the beginner is concerned.  Experienced Lispers understand
> that what Lisp calls a "symbol" is a type of object, not a name or
> character string.  A symbol (i.e., an object) is created whenever a
> variable is introduced into the program, and the symbol has a field
> called the "print name" that gets set to the name of the variable.
> Since variables and functions have separate namespaces, the symbol also
> has a variable field and a function field to keep track of the variables
> and functions that have the same name as the print name of the symbol.
>
> --
> Danwww.prairienet.org/~dsb

Dan, this is another very clear and short explanation. I can grok
this. Thanks again. Is it a technically and perfectly correct
explanation? I know that at least most or much of it is.

I am not sure that a symbol is really just an object though. Is it?
Isn't an unbound symbol just a `symbol object'? (Does an unbound
symbol take up space? Or is it just the same as an inexistent symbol?)
Where you wrote `i.e., an object' was your implication that it is just
a certain type of object, i.e., a `symbol object'? I think that is
what you are saying. One thing I didn't understand before was the
concept of a `print name'. Isn't that field (Is `field' the right
word? Would `part' sound more implementation neutral?) used otherwise
than just as a `print name'?

Your last sentence is fairly clear to me. What I would like to be very
clear about is where the name of the function is stored (isn't it in
the symbol having that function as a value?). Likewise I'd like to
know whether a variable name is handled in a similar way.
From: Dan Bensen
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <es93ms$a7h$1@wildfire.prairienet.org>
Thomas Elam wrote:
> I am not sure that a symbol is really just an object though. Is it?

Yes, definitely.  CLtL2 ch10:

"A Lisp symbol is a data object that has three user-visible components:
     * The property list
     * The print name
     * The package cell"

> Isn't an unbound symbol just a `symbol object'? (Does an unbound
> symbol take up space? Or is it just the same as an inexistent symbol?)

It takes up space.  You can create an unbound symbol (object) with the 
function GENSYM.  It will have a print name (a member variable), but you 
won't be able to use it (no binding).

> Where you wrote `i.e., an object' was your implication that it is just
> a certain type of object, i.e., a `symbol object'?

Right, although of course it's a very important type.  A symbol is
created every time you introduce a new special (not lexical) identifier 
in your code.

>  One thing I didn't understand before was the
> concept of a `print name'. Isn't that field (Is `field' the right
> word? Would `part' sound more implementation neutral?) used otherwise
> than just as a `print name'?

It's a field in the C sense of the word, a member variable.  In CL, it's 
called a "slot".  Other than printing, I'm not sure what all its uses are.

> What I would like to be very
> clear about is where the name of the function is stored (isn't it in
> the symbol having that function as a value?). Likewise I'd like to
> know whether a variable name is handled in a similar way.

I'm not sure what you mean.  Every identifier has an entry in a symbol 
table somewhere.  The entry for a nonlexical name points to the symbol 
that was created for that name instead of directly to the data.  The 
symbol has the name stored in its print-name slot.  Someone else should
explain how the symbol keeps track of its variables and functions.
The plist must have pointers to them, but I don't know the details.

-- 
Dan
www.prairienet.org/~dsb
From: Rob Warnock
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <m6udnUUieYp9h3XYnZ2dnUVZ_uCinZ2d@speakeasy.net>
Dan Bensen  <··········@cyberspace.net> wrote:
+---------------
| Thomas Elam wrote:
| > I am not sure that a symbol is really just an object though. Is it?
| 
| Yes, definitely.  CLtL2 ch10:
| "A Lisp symbol is a data object that has three user-visible components:
|      * The property list
|      * The print name
|      * The package cell"
+---------------

Please don't use CLtL2 when trying to give definitive references;
it's not normative. The CLHS lists *five* standard attributes for
symbols:

    http://alu.org/HyperSpec/Body/syscla_symbol.html
    System Class SYMBOL 
    ...
    Symbols have the following attributes. For historical reasons,
    these are sometimes referred to as cells, although the actual
    internal representation of symbols and their attributes is
    implementation-dependent. 

    Name
      ...
    Package
      ...
    Property list
      ...
    Value
      ...
    Function
      ...

+---------------
| > Isn't an unbound symbol just a `symbol object'? (Does an unbound
| > symbol take up space? Or is it just the same as an inexistent symbol?)
| 
| It takes up space.  You can create an unbound symbol (object) with the 
| function GENSYM.  It will have a print name (a member variable), but you 
| won't be able to use it (no binding).
+---------------

Sure you can use it, just not for its "value"! You can use it for
its identity, e.g., as an EOF marker for READ, or a sentinal in a
search, or lots of other things. The CLHS (same URL as above) says
as much:

    Symbols are used for their object identity to name various
    entities in Common Lisp, including (but not limited to)
    linguistic entities such as variables and functions.

And if you SETF its SYMBOL-VALUE (see below), then you can even
use it as a variable! [Though be careful not to lose the last
reference to it, since unlike an interned symbol you can't get 
it back knowing only its name.]

+---------------
| > What I would like to be very clear about is where the name of
| > the function is stored (isn't it in the symbol having that
| > function as a value?). Likewise I'd like to know whether a
| > variable name is handled in a similar way.
| 
| I'm not sure what you mean.  Every identifier has an entry in a symbol 
| table somewhere.  The entry for a nonlexical name points to the symbol 
| that was created for that name instead of directly to the data.  The 
| symbol has the name stored in its print-name slot.  Someone else should
| explain how the symbol keeps track of its variables and functions.
| The plist must have pointers to them, but I don't know the details.
+---------------

While the plist *was* used for such things in some ancient Lisps, in
ANSI CL the plist is no longer used for "value" and "function"; they
now have their own dedicated (virtual) slots, accessed with SYMBOL-VALUE
and SYMBOL-FUNCTION, respectively.

I say "virtual" slots, since in some implementations either or both
of "value" and "function" might not be stored in structure-like slots
per se. E.g., in CMUCL there is no "function slot" per se in the symbol
object; instead, SYMBOL-FUNCTION refers to an internal "INFO" table
(that also contains lots of other stuff, such as documentation).
Similarly, some CLs with threads don't store the values of global
variables directly in the symbols, but in per-thread structures
accessed indirectly through the symbols, e.g., using a "global
variable index" slot in the symbol, say.

Still, unless one is a maintainer of the internals of some specific
implementation, one seldom needs to care whether the "slots" of a
symbol are "real" or not. For everyday purposes, one might as well
say a symbol "has" value & function "slots" [as well as name, package,
and plist "slots"], since the standard accessors provide the appearance
that they do.


-Rob

p.s. Another aspect of Elam's question wasn't properly answered:
+---------------
| > What I would like to be very clear about is where the name of
| > the function is stored (isn't it in the symbol having that
| > function as a value?).
+---------------

It *might* be, but not all functions have names [think of a LAMBDA].
That is, there is a mapping from "name x lexical_environment --> function",
if such a function exists, but there is no guarantee that there is
a mapping from "function --> name".

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Dan Bensen
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <es97rh$bgl$1@wildfire.prairienet.org>
Rob Warnock wrote:

> | > Isn't an unbound symbol just a `symbol object'? (Does an unbound
> | > symbol take up space? Or is it just the same as an inexistent symbol?)
> | 
> | It takes up space.  You can create an unbound symbol (object) with the 
> | function GENSYM.  It will have a print name (a member variable), but you 
> | won't be able to use it (no binding).
> +---------------
> 
> Sure you can use it, just not for its "value"! 
> And if you SETF its SYMBOL-VALUE (see below), then you can even
> use it as a variable! [Though be careful not to lose the last
> reference to it, since unlike an interned symbol you can't get 
> it back knowing only its name.]

Which was exactly my point.  The "it" in "you won't be able to use it"
referred to the print name, not the object itself.  The main question
was whether the object can exist without being bound, which it can.

> | Someone else should
> | explain how the symbol keeps track of its variables and functions.
> | The plist must have pointers to them, but I don't know the details.
> +---------------
> 
> <explanation>

Thank you.

-- 
Dan
www.prairienet.org/~dsb
From: Rob Warnock
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <JNSdnZZ-yO3v0HfYnZ2dnUVZ_qKqnZ2d@speakeasy.net>
Dan Bensen  <··········@cyberspace.net> wrote:
+---------------
| Rob Warnock wrote:
| > | It takes up space. You can create an unbound symbol (object) with the 
| > | function GENSYM. It will have a print name (a member variable), but you 
| > | won't be able to use it (no binding).
| > +---------------
| > 
| > Sure you can use it, just not for its "value"! 
| 
| Which was exactly my point.  The "it" in "you won't be able to use it"
| referred to the print name, not the object itself.
+---------------

Well, even there, you *can* access the print name of an
uninterned symbol, as long as you hold a reference to it:

    > (make-symbol "An uninterned SYMBOL")

    #:|An uninterned SYMBOL|
    > (symbol-name *)

    "An uninterned SYMBOL"
    > (format t "Print name: ~a~%" (symbol-name **))
    Print name: An uninterned SYMBOL
    NIL
    > 

You just can't get a reference to it knowing *only* the print name...


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172853385.910397.33240@8g2000cwh.googlegroups.com>
On Mar 2, 1:06 pm, Dan Bensen <··········@cyberspace.net> wrote:
> Thomas Elam wrote:
> > I am not sure that a symbol is really just an object though. Is it?
>
> Yes, definitely.  CLtL2 ch10:
>
> "A Lisp symbol is a data object that has three user-visible components:
>      * The property list
>      * The print name
>      * The package cell"
>
> > Isn't an unbound symbol just a `symbol object'? (Does an unbound
> > symbol take up space? Or is it just the same as an inexistent symbol?)
>
> It takes up space.  You can create an unbound symbol (object) with the
> function GENSYM.  It will have a print name (a member variable), but you
> won't be able to use it (no binding).
>
> > Where you wrote `i.e., an object' was your implication that it is just
> > a certain type of object, i.e., a `symbol object'?
>
> Right, although of course it's a very important type.  A symbol is
> created every time you introduce a new special (not lexical) identifier
> in your code.
>
> >  One thing I didn't understand before was the
> > concept of a `print name'. Isn't that field (Is `field' the right
> > word? Would `part' sound more implementation neutral?) used otherwise
> > than just as a `print name'?
>
> It's a field in the C sense of the word, a member variable.  In CL, it's
> called a "slot".  Other than printing, I'm not sure what all its uses are.
>
> > What I would like to be very
> > clear about is where the name of the function is stored (isn't it in
> > the symbol having that function as a value?). Likewise I'd like to
> > know whether a variable name is handled in a similar way.
>
> I'm not sure what you mean.  Every identifier has an entry in a symbol
> table somewhere.  The entry for a nonlexical name points to the symbol
> that was created for that name instead of directly to the data.  The
> symbol has the name stored in its print-name slot.  Someone else should
> explain how the symbol keeps track of its variables and functions.
> The plist must have pointers to them, but I don't know the details.
>
> --
> Danwww.prairienet.org/~dsb


Rainer (Hi!), Dan, Rob, and Dan again, you have all given me a lot to
think about. Thanks! It is all becoming clearer. Even CLHS is becoming
clearer! I'll think about the 26 messages in this thread for quite a
while, at first especially the ones answering my questions about
symbols.
From: Vassil Nikolov
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <yy8vwt1yy9ld.fsf@eskimo.com>
On Fri, 02 Mar 2007 06:06:12 -0600, Dan Bensen <··········@cyberspace.net> said:
| ...
|  A symbol is
| created every time you introduce a new special (not lexical) identifier 
| in your code.

  It's more involved than that.  A symbol is typically [1] created by INTERN
  (if it did not already exist) as called by READ when an S-expression is
  read.  If that S-expression is part of lisp source, a symbol would be
  created whether or not it names a lexical variable.  _However_, if it
  does, if the code is compiled, and then if the compiled code is loaded
  into a(nother) lisp image without loading the source, then (most
  likely) that symbol would not come into existence any more if all of its
  occurrences were to represent that lexical variable.  Compare this to

    (defun foo (x) (cons 'x x))

  where X will be created when the lexical variable it names is read in
  the lambda list of the function, but then the very same symbol will be
  the car of FOO's return value even if after compilation the lexical
  variable X is no longer represented by a symbol (but by a number in
  the object code).

  [1] NB: "typically", because there are a few other scenarios, but the
      above is by far the most popular.  In fact, that symbols are
      typically interned is a very important feature.  For example,
      this is what makes associative and property lists with symbols as
      keys (the usual kind of a- and p-lists) more efficient than hash
      tables with strings as keys when the number of key-value pairs is
      relatively small (an important case).

  ---Vassil.


-- 
mind mate, n.
  One of two persons mentally compatible with each other (cf. soul mate).
From: Rainer Joswig
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <joswig-884670.10342202032007@news-europe.giganews.com>
In article <························@8g2000cwh.googlegroups.com>,
 "Thomas Elam" <·······@gmail.com> wrote:

> On Mar 2, 7:55 am, Dan Bensen <··········@cyberspace.net> wrote:
> > Thomas Elam wrote:
> > > do, but not how. I think I even don't understand symbols very well,
> > > coming from a C background as I am. An object that is a symbol? It's
> > > hard for me to get used to. It's not even a string. Wow. Different.
> >
> > I had trouble with that too.  The word "symbol" is an unfortunate choice
> > as far as the beginner is concerned.  Experienced Lispers understand
> > that what Lisp calls a "symbol" is a type of object, not a name or
> > character string.  A symbol (i.e., an object) is created whenever a
> > variable is introduced into the program, and the symbol has a field
> > called the "print name" that gets set to the name of the variable.
> > Since variables and functions have separate namespaces, the symbol also
> > has a variable field and a function field to keep track of the variables
> > and functions that have the same name as the print name of the symbol.
> >
> > --
> > Danwww.prairienet.org/~dsb
> 
> Dan, this is another very clear and short explanation. I can grok
> this. Thanks again. Is it a technically and perfectly correct
> explanation? I know that at least most or much of it is.
> 
> I am not sure that a symbol is really just an object though. Is it?
> Isn't an unbound symbol just a `symbol object'? (Does an unbound
> symbol take up space? Or is it just the same as an inexistent symbol?)
> Where you wrote `i.e., an object' was your implication that it is just
> a certain type of object, i.e., a `symbol object'? I think that is
> what you are saying. One thing I didn't understand before was the
> concept of a `print name'. Isn't that field (Is `field' the right
> word? Would `part' sound more implementation neutral?) used otherwise
> than just as a `print name'?
> 
> Your last sentence is fairly clear to me. What I would like to be very
> clear about is where the name of the function is stored (isn't it in
> the symbol having that function as a value?). Likewise I'd like to
> know whether a variable name is handled in a similar way.



Think of a symbol as a specialized vector.

The vector has slots:

* name
* value
* function
* property list
* package

So a symbol is kind of a vector with a type tag SYMBOL.
You can set and read these slots with various functions.

Always if you create a symbol, you get something like this.


Object in Lisp means generally all Lisp data. A string is an object.
More specially there are CLOS objects. A string is not
a CLOS object. A symbol is not a CLOS object.


? (make-symbol "FOO")
#:FOO

We have a symbol.

? (setf s1 *)
#:FOO

Saving it to same variable.


? (symbol-name s1)
"FOO"

The name.

? (symbol-value s1)
> Error: Unbound variable: #:FOO
> While executing: CCL::TOPLEVEL-EVAL, in process listener(1).
> Type :GO to continue, :POP to abort, :R for a list of available restarts.
> If continued: Retry getting the value of #:FOO.
> Type :? for other options.
1 > :pop


It has no value yet. It is unbound.


? (symbol-package s1)
NIL


No package for this symbol.



? (symbol-function s1)
> Error: Undefined function: #:FOO
> While executing: SYMBOL-FUNCTION, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
1 > :pop


It has no function yet.


? (symbol-plist s1)
NIL

The property list is empty.


We created the symbol with MAKE-SYMBOL.
Typically symbols will be created for example by the reader.
It reads a Lisp form and creates symbols where necessary or
looks up existing symbols.

There we have the lookup. Where does it do that? In packages.
Packages are, say, hashtables for symbols. Hashed by the name.
So you can access the the symbol in a package by the symbol name.
If a symbol is accessible from a package, then it is interned.



? (setf (symbol-value s1) "hi, I'm a value")
"hi, I'm a value"

? (symbol-value s1)
"hi, I'm a value"

Now the symbol has a value.

? (setf (symbol-function s1) (lambda () (print "hi, I'm a function")))
#<Anonymous Function #x300040DFCC0F>
? (symbol-function s1)
#<Anonymous Function #x300040DFCC0F>
? (funcall (symbol-function s1))

"hi, I'm a function" 
"hi, I'm a function"

Now the symbol has a function.


? s1               
#:FOO

our symbol.

? (import s1 (find-package "CL-USER"))
T

Now our symbol has a package.

? s1
FOO
? 

? (symbol-package s1)
#<Package "COMMON-LISP-USER">


Now we can type FOO. The reader looks up "FOO" in package "CL-USER"
finds our symbol.

? (find-symbol "FOO" "CL-USER")
FOO
:INTERNAL


? (eq 'foo s1)
T

so the symbol FOO and the value of the variable s1 are the same.


? foo
"hi, I'm a value"
? (foo)

"hi, I'm a function" 
"hi, I'm a function"

? (describe 'foo)
Symbol: FOO
Non-special Variable, Function
INTERNAL in package: #<Package "COMMON-LISP-USER">
Print name: "FOO"
Value: "hi, I'm a value"
Function: #<Anonymous Function #x300040DFCC0F>
Arglist: NIL
Plist: NIL


But what about DEFVAR, DEFUN, ...

DEFVAR sets the value of a symbol (if it is unbound).
DEFPARAMETER sets the value of a symbol.
DEFUN sets the function of a symbol.
From: Thierry Pirot
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <83vehjrmee.fsf@thierrypirot.net>
Rainer Joswig  writes:
> 
> But what about DEFVAR, DEFUN, ...
> 
> DEFVAR sets the value of a symbol (if it is unbound).
> DEFPARAMETER sets the value of a symbol.
> DEFUN sets the function of a symbol.
>
But what about LET, FLET, binding forms... ?  
I'd like to grok 
what they set, 
how are lexical identifiers 'registered'...  

-- 
   Take it Easy          Don't worry            Be Happy

                           Thierry

�������o�o��������o�o��������o�o��������o�o��������o�o�������
From: Pascal Bourguignon
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <87y7m98nvm.fsf@voyager.informatimago.com>
Thierry Pirot <·@thierrypirot.net> writes:

> Rainer Joswig  writes:
>> 
>> But what about DEFVAR, DEFUN, ...
>> 
>> DEFVAR sets the value of a symbol (if it is unbound).
>> DEFPARAMETER sets the value of a symbol.
>> DEFUN sets the function of a symbol.
>>
> But what about LET, FLET, binding forms... ?  
> I'd like to grok 
> what they set, 
> how are lexical identifiers 'registered'...  

They are not.  That is, symbols used to name lexical variables and
functions are only maintained by the compiler; they disappear in the
compiled program.  The compiler decides at what address to store each
lexical variable, and just substitute this address for the symbol in
the target code.

For example, see how clisp disassembles a function with two lexical
variables, x and y, and compare it with how it does the same for a
function with one lexical variable, x, and a dynamic variable, *y*.
In the first case,  you don't see any reference to x or y in the
object code; in the later, you can see that the symbol *y* is refered
to from the object code.


So, the point is that symbols are an important compiler data structure
(in any compiler text book you can read a chapter about symbols and
symbol tables), but in lisp, this compiler data structure is also
available at run-time, so we can easily manipulate code at runtime too.



C/USER[5]> (disassemble (defun f (x) (let ((y (+ 2 x))) (* 3 y))))


Disassembly of function F
(CONST 0) = 2
(CONST 1) = 3
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
7 byte-code instructions:
0     (CONST&PUSH 0)                      ; 2
1     (LOAD&PUSH 2)
2     (CALLSR&PUSH 2 53)                  ; +
5     (CONST&PUSH 1)                      ; 3
6     (LOAD&PUSH 1)
7     (CALLSR 2 55)                       ; *
10    (SKIP&RET 3)
NIL
C/USER[6]> (disassemble (defun f (x) (* 3 (+ x *y*))))

WARNING in F :
*Y* is neither declared nor bound,
it will be treated as if it were declared SPECIAL.

Disassembly of function F
(CONST 0) = 3
(CONST 1) = *Y*
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
reads special variable: (*Y*)
6 byte-code instructions:
0     (CONST&PUSH 0)                      ; 3
1     (LOAD&PUSH 2)
2     (GETVALUE&PUSH 1)                   ; *Y*
4     (CALLSR&PUSH 2 53)                  ; +
7     (CALLSR 2 55)                       ; *
10    (SKIP&RET 2)
NIL
C/USER[7]> 


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
        Un chat errant
se soulage
        dans le jardin d'hiver
                                        Shiki
From: Thierry Pirot
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <83irdaot4i.fsf@thierrypirot.net>
Pascal Bourguignon writes:
> Thierry Pirot writes:
> 
> > But what about LET, FLET, binding forms... ?  
> > I'd like to grok 
> > what they set, 
> > how are lexical identifiers 'registered'...  
> 
> They are not.  That is, symbols used to name lexical variables and
> functions are only maintained by the compiler; they disappear in the
> compiled program.  The compiler decides at what address to store each
> lexical variable, and just substitute this address for the symbol in
> the target code.
> 
Is this a compilation issue or a requirement of the standard, and 
what about an implementation without compilation --- if this means anything --- ?  
Footnote 3 of http://www.flownet.com/gat/specials.pdf 
says it's not in the standard.  
The standard states, for example, that 
 SYMBOL-VALUE cannot access the value of a lexical variable; 
 BOUND determines only whether a symbol has a value in the global environment; 
any lexical bindings are ignored; 
 SYMBOL-FUNCTION cannot access the value of a lexical function name 
produced by FLET or LABELS; it can access only the global function value 
--- my questions stem from the fact that 
I once wanted to apply SYMBOL-FUNCTION on a local function name.  
So I wonder 
why riddance or unavailability of symbols for lexical variables is at the menu, 
what could be the pros and cons ? 

> For example, see how clisp disassembles a function with two lexical
> variables, x and y, and compare it with how it does the same for a
> function with one lexical variable, x, and a dynamic variable, *y*.
> In the first case,  you don't see any reference to x or y in the
> object code; in the later, you can see that the symbol *y* is refered
> to from the object code.
> 
> So, the point is that symbols are an important compiler data structure
> (in any compiler text book you can read a chapter about symbols and
> symbol tables), but in lisp, this compiler data structure is also
> available at run-time, so we can easily manipulate code at runtime too.


That has been helpful.  Thanks.  
-- 
   Take it Easy          Don't worry            Be Happy

                           Thierry

�������o�o��������o�o��������o�o��������o�o��������o�o�������
From: Vassil Nikolov
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <yy8vlki57hvc.fsf@eskimo.com>
On 10 Mar 2007 01:10:53 +0100, Thierry Pirot <·@thierrypirot.net> said:
| ...
|  SYMBOL-VALUE cannot access the value of a lexical variable; 

  Because a lexical variable is not represented at run-time by a
  first-class object (it is represented by a first-class object, a
  symbol, only at compile-time).

|  BOUND determines only whether a symbol has a value in the global environment; 
   ^^^^^P

  Actually, if a symbol represents a bound special variable, which may
  or may not be in the global environment:

    ;; assuming the symbol foo is a fresh one, what does the following
    ;; return, and why:
    (values
      (boundp 'foo)
      (let ((foo 0))
        (boundp 'foo))
      (let ((foo 0))
        (declare (special foo))
        (boundp 'foo)))

| any lexical bindings are ignored; 

  You don't need a run-time check for lexical bindings, because by
  definition they are lexically apparent, i.e. can be detected (at least
  in principle) by static analysis.

|  SYMBOL-FUNCTION cannot access the value of a lexical function name 
| produced by FLET or LABELS;

  But FUNCTION can:

    (progn
      (defun foo () 'global-foo)
      (flet ((foo () 'local-foo))
        (values
          (funcall (symbol-function 'foo))
          (funcall (function foo)))))

  In one sentence, lexical bindings (with LET of lexical variables,
  FLET, LABELS) are handled by the compiler, while special bindings
  (with LET of variables declared special including those with DEFVAR
  and DEFPARAMETER) are handled by the run-time system.

  ---Vassil.


-- 
Is your code free of side defects?
From: Ari Johnson
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <m2r6s89lum.fsf@hermes.theari.com>
"Thomas Elam" <·······@gmail.com> writes:

> I did read at least some of that section. I would love to find a good
> book midway in tone between PCL and ANSI CL. I think it will take me
> at least 2 or 3 hours on one of my better days to grok this stuff
> well. I think that I will finally get it deeply if I can understand
> the order of evaluation (or nonevaluation) and the (nonmacro-related)
> quoting and quasiquoting. I think I fully appreciate *what* macros can
> do, but not how. I think I even don't understand symbols very well,
> coming from a C background as I am. An object that is a symbol? It's
> hard for me to get used to. It's not even a string. Wow. Different.
> But I love it.

Try reading the link below.  It's a friend's wiki (disclaimer: I wrote
this particular article).  His intention with the wiki is not to
provide tutorials or normal documentation, but rather documentation on
things that are hard to find in one place elsewhere.  For instance,
weird gcc output options and how to manually trace a C call stack.

Anyhow, the Lisp article is a useful collection of aids to your
understanding.  See in particular "Backquote Syntax" and "Macros."

Feel free to edit it, too.  I see that others have done so a bit.
Thanks! :)

http://devpit.org/wiki/Lisp
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172825512.559617.249770@64g2000cwx.googlegroups.com>
On Mar 2, 7:54 am, Ari Johnson <·········@gmail.com> wrote:
> "Thomas Elam" <·······@gmail.com> writes:
> > I did read at least some of that section. I would love to find a good
> > book midway in tone between PCL and ANSI CL. I think it will take me
> > at least 2 or 3 hours on one of my better days to grok this stuff
> > well. I think that I will finally get it deeply if I can understand
> > the order of evaluation (or nonevaluation) and the (nonmacro-related)
> > quoting and quasiquoting. I think I fully appreciate *what* macros can
> > do, but not how. I think I even don't understand symbols very well,
> > coming from a C background as I am. An object that is a symbol? It's
> > hard for me to get used to. It's not even a string. Wow. Different.
> > But I love it.
>
> Try reading the link below.  It's a friend's wiki (disclaimer: I wrote
> this particular article).  His intention with the wiki is not to
> provide tutorials or normal documentation, but rather documentation on
> things that are hard to find in one place elsewhere.  For instance,
> weird gcc output options and how to manually trace a C call stack.
>
> Anyhow, the Lisp article is a useful collection of aids to your
> understanding.  See in particular "Backquote Syntax" and "Macros."
>
> Feel free to edit it, too.  I see that others have done so a bit.
> Thanks! :)
>
> http://devpit.org/wiki/Lisp

Ari, thanks for the link! Your writing looks very concentrated and
straightforward, just hitting the high points. I think this is what
I'm ready for.
From: Daniel Janus
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <slrneueeo1.h6a.przesunmalpe@students.mimuw.edu.pl>
Dnia 01.03.2007 Joel Wilsson <············@gmail.com> napisa�/a:

> (defmacro pop-fields (place-to-pop &rest places-to-set)
>   `(progn ,@(loop for place in places-to-set
>                collect `(setf ,place (pop ,place-to-pop)))))

Here's my shot, using MAPCAR instead of LOOP:

(defmacro pop-fields (place-to-pop &rest places-to-set)
  `(progn ,@(mapcar #'(lambda (x) `(setf ,x (pop ,place-to-pop))) 
                    places-to-set)))

-- 
Daniel 'Nathell' Janus, GG #1631668, ············@nathell.korpus.pl
"Though a program be but three lines long, someday it will have to be
maintained."
      -- The Tao of Programming
From: Frode Vatvedt Fjeld
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <2h4pp4211l.fsf@vserver.cs.uit.no>
"Thomas Elam" <·······@gmail.com> writes:

> I just want something that would work like this:
> 
> (pop-fields list a b c d)
> => (setf a (pop list))
>      (setf b (pop list))
>      (setf c (pop list))
>      (setf d (pop list))

Here's an attempt:

  (defmacro pop-fields (pop-place &rest target-places)
     `(setf ,@(loop for target-place in target-places
                append (list target-place `(pop ,pop-place)))))

> Any help would be greatly appreciated.

The above is my 15-seconds effort, and may or may not work. Either way
it should provide some clues.

-- 
Frode Vatvedt Fjeld
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172779840.998639.262840@31g2000cwt.googlegroups.com>
On Mar 2, 12:53 am, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
> "Thomas Elam" <·······@gmail.com> writes:
> > I just want something that would work like this:
>
> > (pop-fields list a b c d)
> > => (setf a (pop list))
> >      (setf b (pop list))
> >      (setf c (pop list))
> >      (setf d (pop list))
>
> Here's an attempt:
>
>   (defmacro pop-fields (pop-place &rest target-places)
>      `(setf ,@(loop for target-place in target-places
>                 append (list target-place `(pop ,pop-place)))))
>
> > Any help would be greatly appreciated.
>
> The above is my 15-seconds effort, and may or may not work. Either way
> it should provide some clues.
>
> --
> Frode Vatvedt Fjeld

It sure works. Thanks! I thought it would be simpler, though.

Is it really necessary to use a macro for this?
From: Frode Vatvedt Fjeld
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <2hzm6wzpi1.fsf@vserver.cs.uit.no>
On Mar 2, 12:53 am, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:

> >   (defmacro pop-fields (pop-place &rest target-places)
> >      `(setf ,@(loop for target-place in target-places
> >                 append (list target-place `(pop ,pop-place)))))

"Thomas Elam" <·······@gmail.com> writes:

> It sure works. Thanks! I thought it would be simpler, though.  Is it
> really necessary to use a macro for this?

Well.. is it really necessary to use a hammer to drive in that nail?
The answer is both yes and no, as you can imagine. The way you asked
your original question, I think strictly speaking the answer is yes, a
macro is really necessary, although in all likelyhood there would be
other ways to solve whatever programming task you are working on.

And, using this particular hammer /is/ rather simple, once you've
tried it a few times and the thumbs have healed somewhat.

-- 
Frode Vatvedt Fjeld
From: Dan Bensen
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <es8gc6$3rs$1@wildfire.prairienet.org>
>> "Thomas Elam" <·······@gmail.com> writes:
>>> (pop-fields list a b c d)
>>> => (setf a (pop list))
>>>      (setf b (pop list))
>>>      (setf c (pop list))
>>>      (setf d (pop list))

> On Mar 2, 12:53 am, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
>>   (defmacro pop-fields (pop-place &rest target-places)
>>      `(setf ,@(loop for target-place in target-places
>>                 append (list target-place `(pop ,pop-place)))))
>>
>>> Any help would be greatly appreciated.
>> The above is my 15-seconds effort, and may or may not work. Either way
>> it should provide some clues.

Thomas Elam wrote:
> Is it really necessary to use a macro for this?

It is if you want to call it exactly the way you wrote it.
pop and setf are both destructive, i.e. they change the variables
themselves, so they need the locations of their arguments, not the
values.  The way you do that is to delay evalution of the arguments,
which is what macros do.  Since all function arguments are evaluated,
a function would have to be called as something like
   (pop-fields 'list 'a 'b 'c 'd).

-- 
Dan
www.prairienet.org/~dsb
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172824149.022134.107570@v33g2000cwv.googlegroups.com>
On Mar 2, 7:36 am, Dan Bensen <··········@cyberspace.net> wrote:
> >> "Thomas Elam" <·······@gmail.com> writes:
> >>> (pop-fields list a b c d)
> >>> => (setf a (pop list))
> >>>      (setf b (pop list))
> >>>      (setf c (pop list))
> >>>      (setf d (pop list))
> > On Mar 2, 12:53 am, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
> >>   (defmacro pop-fields (pop-place &rest target-places)
> >>      `(setf ,@(loop for target-place in target-places
> >>                 append (list target-place `(pop ,pop-place)))))
>
> >>> Any help would be greatly appreciated.
> >> The above is my 15-seconds effort, and may or may not work. Either way
> >> it should provide some clues.
> Thomas Elam wrote:
> > Is it really necessary to use a macro for this?
>
> It is if you want to call it exactly the way you wrote it.
> pop and setf are both destructive, i.e. they change the variables
> themselves, so they need the locations of their arguments, not the
> values.  The way you do that is to delay evalution of the arguments,
> which is what macros do.  Since all function arguments are evaluated,
> a function would have to be called as something like
>    (pop-fields 'list 'a 'b 'c 'd).
>
> --
> Danwww.prairienet.org/~dsb

Dan, your explanation is simple and sweet and very clear. Thanks.
This is the high point of what I need to keep in mind.
From: Matthias Benkard
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172836215.813528.26580@n33g2000cwc.googlegroups.com>
> The way you do that is to delay evalution of the arguments,
> which is what macros do.  Since all function arguments are evaluated,
> a function would have to be called as something like
>    (pop-fields 'list 'a 'b 'c 'd).

Hmm...  Regardless of how POP-FIELDS is implemented, if A, B, C and D
are lexical variables, that's not going to work, is it?  You can't
access lexical variables by name only, because they are only visible
within their lexical scope.

So you do need a macro here.
From: Kaz Kylheku
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172782348.936082.299950@h3g2000cwc.googlegroups.com>
On Mar 1, 11:53 am, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
> Here's an attempt:
>
>   (defmacro pop-fields (pop-place &rest target-places)
>      `(setf ,@(loop for target-place in target-places
>                 append (list target-place `(pop ,pop-place)))))

Why mix backquote and regular list construction?

   append `(,target-place (pop ,pop-place))


Suggested more generic design:

   ;; multi-setf: evaluate the right
   ;; expression as many times as there are
   ;; assignment places in the left list,
   ;; and store the successive values into
   ;; each place.

   (msetf (a b c d) (pop list)) ;; like pop-fields

   (msetf (a b c d) 0) ;; set four vars to 0

   (msetf (a b c d) (incf counter)) ;; consecutive integers
From: Matthias Benkard
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172794390.329982.141550@j27g2000cwj.googlegroups.com>
> Suggested more generic design:
>
>    ;; multi-setf: evaluate the right
>    ;; expression as many times as there are
>    ;; assignment places in the left list,
>    ;; and store the successive values into
>    ;; each place.

As an exercise, I've implemented something even more generic:

 (defmacro doplaces ((name &rest places) &body body)
   `(progn
      ,@(loop for place in places
              collect `(symbol-macrolet ((,name ,place))
                         ,@body))))

Use it like this:

 (doplaces (place a b c d)
   (setf place (pop list)))

I'm a newbie to macro writing, too, though.  So I'd like to ask: Is
DOPLACES okay as it is, or is there room for improvement?  In
particular, does the (name &rest places) part of the lambda list feel
more or less idiomatic, or would an experienced Lisper prefer (name
places) or something else entirely?

Matthias
From: Vassil Nikolov
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <yy8vlkiggucc.fsf@eskimo.com>
On 1 Mar 2007 16:13:10 -0800, "Matthias Benkard" <··········@gmail.com> said:
| ...
|  (doplaces (place a b c d)
|    (setf place (pop list)))

| ... Is DOPLACES okay as it is, or is there room for improvement?

  I suppose you can get a variety of opinions here; in my view, such a macro
  would lead to side effects that are too concentrated for my liking...

  ---Vassil.


-- 
mind mate, n.
  One of two persons mentally compatible with each other (cf. soul mate).
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172816065.056643.222040@j27g2000cwj.googlegroups.com>
On Mar 2, 1:52 am, "Kaz Kylheku" <········@gmail.com> wrote:
> On Mar 1, 11:53 am, Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
>
> > Here's an attempt:
>
> >   (defmacro pop-fields (pop-place &rest target-places)
> >      `(setf ,@(loop for target-place in target-places
> >                 append (list target-place `(pop ,pop-place)))))
>
> Why mix backquote and regular list construction?
>
>    append `(,target-place (pop ,pop-place))
>
> Suggested more generic design:
>
>    ;; multi-setf: evaluate the right
>    ;; expression as many times as there are
>    ;; assignment places in the left list,
>    ;; and store the successive values into
>    ;; each place.
>
>    (msetf (a b c d) (pop list)) ;; like pop-fields
>
>    (msetf (a b c d) 0) ;; set four vars to 0
>
>    (msetf (a b c d) (incf counter)) ;; consecutive integers


Cool idea.
From: Kalle Olavi Niemitalo
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <874pp41tu7.fsf@Astalo.kon.iki.fi>
"Thomas Elam" <·······@gmail.com> writes:

> I just want something that would work like this:
>
> (pop-fields list a b c d)
> => (setf a (pop list))
>      (setf b (pop list))
>      (setf c (pop list))
>      (setf d (pop list))

A macro cannot expand to a sequence of forms.  It must expand to
a single form, which could in this case be one of these:

    ;; Wrap them all in a PROGN.  Note that you can even use this
    ;; for forms that are expected to be at top level.
    (progn
      (setf a (pop list))
      (setf b (pop list))
      (setf c (pop list))
      (setf d (pop list)))

    ;; Alternatively, take advantage of SETF's flexibility.
    (setf a (pop list)
          b (pop list)
          c (pop list)
          d (pop list))

The former is easier to implement:

    (defmacro pop-fields (from-variable &rest to-places)
      `(progn
         ,@(loop for to-place in to-places
                 collect `(setf ,to-place (pop ,from-variable)))))

Note however that this macro does not work right if the first
argument is a form that is not merely the name of a variable.
The form gets evaluated multiple times, and this matters if
it has side effects or uses the values of the variables to
which the popped values are being stored.

    (let (a b (i 0) (v (vector '(hassle burden effort)
                               '(concept paradigm idea)
                               '(precious bodily fluids))))
      (pop-fields (aref v (incf i)) a b)
      (list a b i v))
 => (CONCEPT PRECIOUS 2 #((HASSLE BURDEN EFFORT)
                          (PARADIGM IDEA)
                          (BODILY FLUIDS)))

To support arbitrary places correctly, use GET-SETF-EXPANSION.
Unfortunately, this makes the macro a lot more complex.

    (defmacro pop-fields (from-place &rest to-places &environment env)
      (multiple-value-bind (vars vals store-vars writer reader)
          (get-setf-expansion from-place env)
        (let ((temp (gensym)))
          `(let* ,(mapcar #'list vars vals)
             ,@(loop for to-place in to-places
                     collect `(setf ,to-place
                                    (let ((,temp ,reader))
                                      (prog1 (pop ,temp)
                                        (multiple-value-bind
                                            ,store-vars ,temp
                                          ,writer)))))))))

    (let (a b (i 0) (v (vector '(hassle burden effort)
                               '(concept paradigm idea)
                               '(precious bodily fluids))))
      (pop-fields (aref v (incf i)) a b)
      (list a b i v))
 => (CONCEPT PARADIGM 1 #((HASSLE BURDEN EFFORT)
                          (IDEA)
                          (PRECIOUS BODILY FLUIDS)))

It may be better to skip this complexity and instead just put a
CHECK-TYPE in the macro to ensure that the first argument is the
name of a variable.
From: Thomas Elam
Subject: Re: Request for help constructing a simple macro
Date: 
Message-ID: <1172856087.626286.9860@s48g2000cws.googlegroups.com>
On Mar 1, 11:29 pm, Kalle Olavi Niemitalo <····@iki.fi> wrote:
> "Thomas Elam" <·······@gmail.com> writes:
> > I just want something that would work like this:
>
> > (pop-fields list a b c d)
> > => (setf a (pop list))
> >      (setf b (pop list))
> >      (setf c (pop list))
> >      (setf d (pop list))
>
> A macro cannot expand to a sequence of forms.  It must expand to
> a single form, which could in this case be one of these:
>
>     ;; Wrap them all in a PROGN.  Note that you can even use this
>     ;; for forms that are expected to be at top level.
>     (progn
>       (setf a (pop list))
>       (setf b (pop list))
>       (setf c (pop list))
>       (setf d (pop list)))
>
>     ;; Alternatively, take advantage of SETF's flexibility.
>     (setf a (pop list)
>           b (pop list)
>           c (pop list)
>           d (pop list))
>
> The former is easier to implement:
>
>     (defmacro pop-fields (from-variable &rest to-places)
>       `(progn
>          ,@(loop for to-place in to-places
>                  collect `(setf ,to-place (pop ,from-variable)))))
>
> Note however that this macro does not work right if the first
> argument is a form that is not merely the name of a variable.
> The form gets evaluated multiple times, and this matters if
> it has side effects or uses the values of the variables to
> which the popped values are being stored.
>
>     (let (a b (i 0) (v (vector '(hassle burden effort)
>                                '(concept paradigm idea)
>                                '(precious bodily fluids))))
>       (pop-fields (aref v (incf i)) a b)
>       (list a b i v))
>  => (CONCEPT PRECIOUS 2 #((HASSLE BURDEN EFFORT)
>                           (PARADIGM IDEA)
>                           (BODILY FLUIDS)))
>
> To support arbitrary places correctly, use GET-SETF-EXPANSION.
> Unfortunately, this makes the macro a lot more complex.
>
>     (defmacro pop-fields (from-place &rest to-places &environment env)
>       (multiple-value-bind (vars vals store-vars writer reader)
>           (get-setf-expansion from-place env)
>         (let ((temp (gensym)))
>           `(let* ,(mapcar #'list vars vals)
>              ,@(loop for to-place in to-places
>                      collect `(setf ,to-place
>                                     (let ((,temp ,reader))
>                                       (prog1 (pop ,temp)
>                                         (multiple-value-bind
>                                             ,store-vars ,temp
>                                           ,writer)))))))))
>
>     (let (a b (i 0) (v (vector '(hassle burden effort)
>                                '(concept paradigm idea)
>                                '(precious bodily fluids))))
>       (pop-fields (aref v (incf i)) a b)
>       (list a b i v))
>  => (CONCEPT PARADIGM 1 #((HASSLE BURDEN EFFORT)
>                           (IDEA)
>                           (PRECIOUS BODILY FLUIDS)))
>
> It may be better to skip this complexity and instead just put a
> CHECK-TYPE in the macro to ensure that the first argument is the
> name of a variable.

Kalle,

Actually, I rather like this complex macro. I can forsee my need to
use its extra capabilities. Thanks a lot! I don't know whether I could
ever have written that!