From: (remember (help lisp))
Subject: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <1126075742.337212.314290@g44g2000cwa.googlegroups.com>
Hi all,
This is my first post to cll, forgive me if I
break any etiqutte(sp?).

Long story short, I am teaching myself Lisp
(and have already heard all the jokes about having
a fool for a teacher and/or a student :-) and
have gotten stuck on something that, to me,
does not make sense.

I have a macro that gets called like this:

(print (my-list 30 45 (print 60)))


--------------------------
1. If a have the macro defined like so:

(defmacro my-list (a &body b)
 `(format t "~a" ,a)
  `,@b)

Then my lisp implementation (gnu clisp) gives me:

*** - READ: the syntax `,@form is undefined behaviour

--------------------------
2. If the macro is defined like this:

(defmacro my-list (a &body b)
 `(format t "~a" ,a)
  `(,@b))

Then my lisp implementation gives me:

*** - EVAL: 45 is not a function name

--------------------------
3. If my macro is defined as:

(defmacro my-list (a &body b)
 `(format t "~a" ,a)
  `(let ((x 20)),@b))

Then my lisp implementation seems to give the correct result:
60
60

(I understand that the second 60 printed is the result of
the evaluation of the (print ..) in the line calling the macro,
and the first should be the result of the
print function in the argument supplied by the caller).

--------------------------
4. However, if I change the macro to:

(defmacro my-list (a &body b)
 `(format t "~a" ,a)
  `(let ((x 20)),@b) (print 42))

Then I get:
42
42

--------------------------
My first question is why I can't use `,@b, nor `(,@b) (see #1,
#2 and #3 above). How else would I backquote a form argument to
a macro without having to have a spurious (let ...)?

My second question is because I dont understand why the
"(print 60)" does not get executed in #4 above. I feel (wrongly,
I know) that the "(print 60)" supplied by the macro caller should
get executed *as well as* the "(print 42)" in the macro form.

I apologise in advance for possibly stupid questions, but have
not found the answer to these questions in the online "Practical
Lisp" (Paul Graham), nor in the lisp tutorial that came with gnu
clisp, nor in the online book "Successfull Lisp" (David Lamkins).

I would also like to apologise if this question is in the cll faq
(Could someone point me to that, please?).

tia
L. K. Manickum

From: Tayssir John Gabbour
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <1126081520.932539.197360@o13g2000cwo.googlegroups.com>
(remember (help lisp)) wrote:
> I have a macro that gets called like this:
>
> (print (my-list 30 45 (print 60)))
>
>
> --------------------------
> 1. If a have the macro defined like so:
>
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `,@b)
>
> Then my lisp implementation (gnu clisp) gives me:
>
> *** - READ: the syntax `,@form is undefined behaviour

That's because the `(... ,@...) syntax is supposed to "splice" a list
into the enclosing form.

So for example:
(list 1 2 3)      => (1 2 3)
`(,(list 1 2 3))  => ((1 2 3))
`(,@(list 1 2 3)) => (1 2 3)
`,@(list 1 2 3)   is undefined by Common Lisp's specification:
    http://www.lisp.org/HyperSpec/Body/sec_2-4-6.html

Basically, the reason it's undefined is because there isn't an
enclosing form to splice it into, so it kind of doesn't make much
conceptual sense. Probably best to assume doing it is an error.


> --------------------------
> My first question is why I can't use `,@b, nor `(,@b) (see #1,
> #2 and #3 above). How else would I backquote a form argument to
> a macro without having to have a spurious (let ...)?

If I understand you correctly, no need for backquote mojo. Just use:
  b
Or if you really like backquote to an unhealthy degree:
  `,b


Others answered your other questions... Remember, macros are somewhat
similar to functions, except they work at a special syntax time (for
example, maybe during compiletime), and they transform one Lisp form
into another. sexp -> sexp.

And you don't really want to go overboard with macros, but I'm sure you
know that...
http://wiki.alu.org/lisp-user-meeting-amsterdam-april-2004#macros-and-codewalkers


Tayssir
From: Frederic
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <slrndht7hg.kf.beal@clipper.ens.fr>
On 2005-09-07, (remember (help lisp)) <····@webmail.co.za> wrote:
> Hi all,
> This is my first post to cll, forgive me if I
> break any etiqutte(sp?).
>
> Long story short, I am teaching myself Lisp
> (and have already heard all the jokes about having
> a fool for a teacher and/or a student :-) and
> have gotten stuck on something that, to me,
> does not make sense.
>
> I have a macro that gets called like this:
>
> (print (my-list 30 45 (print 60)))
>
>
> --------------------------
> 1. If a have the macro defined like so:
>
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `,@b)
>
> Then my lisp implementation (gnu clisp) gives me:
>
> *** - READ: the syntax `,@form is undefined behaviour
>
> --------------------------
> 2. If the macro is defined like this:
>
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(,@b))
>
> Then my lisp implementation gives me:
>
> *** - EVAL: 45 is not a function name
>
> --------------------------
> 3. If my macro is defined as:
>
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(let ((x 20)),@b))
>
> Then my lisp implementation seems to give the correct result:
> 60
> 60
>
> (I understand that the second 60 printed is the result of
> the evaluation of the (print ..) in the line calling the macro,
> and the first should be the result of the
> print function in the argument supplied by the caller).
>
> --------------------------
> 4. However, if I change the macro to:
>
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(let ((x 20)),@b) (print 42))
>
> Then I get:
> 42
> 42
>
> --------------------------
> My first question is why I can't use `,@b, nor `(,@b) (see #1,
> #2 and #3 above). How else would I backquote a form argument to
> a macro without having to have a spurious (let ...)?

(defmacro my-list (a &body b)
  `(progn (format t "~a" ,a)
          ,@b))

A macro works like a function�: if you write
(defun foo (x)
  form1
  form2)
, then the return value of foo is the return value of form2.
Hence,
(defmacro foo (x)
  compute-list-1
  compute-list-2)
translates foo into the second list.
(E.g., you can use macroexpand to check this�:
?  (defmacro foo ()
     '(print 'Vanishes)
     '(print 'Hello-world))
? (macroexpand '(foo))
 (PRINT 'HELLO-WORLD)

> My second question is because I dont understand why the
> "(print 60)" does not get executed in #4 above. I feel (wrongly,
> I know) that the "(print 60)" supplied by the macro caller should
> get executed *as well as* the "(print 42)" in the macro form.

Use macroexpand�: 
? (defmacro my-list (a &body b)
    `(format t "~a" ,a)
    `(let ((x 20)),@b) (print 42))
? (macroexpand '(my-list 30 45 (print 42)))
42
42

Why is that�?  Because... you added an extra closing bracket�!
(just after ,@b).  Rather write...

(defmacro my-list (a &body b)
  `(format t "~a" ,a)
  `(let ((x 20)) ,@b (print 42)))

And, like I said before, if you do that the first line has no effect.
The final version could be�:

(defmacro my-list (a &body b)
  `(progn
     (format t "~a" ,a)
     (let ((x 20))
        ,@b
        (print 42))))

> I apologise in advance for possibly stupid questions, but have
> not found the answer to these questions in the online "Practical
> Lisp" (Paul Graham), nor in the lisp tutorial that came with gnu
> clisp, nor in the online book "Successfull Lisp" (David Lamkins).

But CLTL (Common Lisp, The Language), looking for "defmacro", could help
you a lot.  Using macroexpand would be a good idea, too...

-- 
 Frederic
From: drewc
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <PaxTe.419220$5V4.342520@pd7tw3no>
(remember (help lisp)) wrote:
> Hi all,
> Long story short, I am teaching myself Lisp
> (and have already heard all the jokes about having
> a fool for a teacher and/or a student :-) and
> have gotten stuck on something that, to me,
> does not make sense.

If your subject line is accurate, and you only have 5 hours experience 
with lisp, i might suggest you hold off on learning macros for a while.

Having said that ...

> 
> I have a macro that gets called like this:
> 
> (print (my-list 30 45 (print 60)))

It would be very helpful if you also posted the desired result of the 
macro, as in what code it should expand to or what the expected result 
of the evaluated code should be,

> --------------------------
> 1. If a have the macro defined like so:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `,@b)
> 
> Then my lisp implementation (gnu clisp) gives me:
> 
> *** - READ: the syntax `,@form is undefined behaviour

Which it is. I'm not quite sure what you expect the  `,@ to produce, but 
according to the CLHS 
(http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_2-4-6.html) 
it is undefined.

On top of that, the syntax of defmacro is "

defmacro name lambda-list [[declaration* | documentation]] form*

Which means that it takes a single form, not two as you have above. If 
you wish to make a macro that expands to multiple forms, you'll need to 
wrap them in a PROGN or something similar.

> --------------------------
> 2. If the macro is defined like this:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(,@b))
> 
> Then my lisp implementation gives me:
> 
> *** - EVAL: 45 is not a function name

Which is correct as well :) If you macroexpand your call you'll notice 
that it expands to the following form (remember, a macro expands to Lisp 
code which is then evaluated) :

CL-USER> (macroexpand-1 '(my-list 30 45 (print 60)))
(45 (PRINT 60))

There is a 45 in the CAR of the list, so this is EVALuated as a function 
call. since there is no function named '45', this fails.


> --------------------------
> 3. If my macro is defined as:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(let ((x 20)),@b))
> 
> Then my lisp implementation seems to give the correct result:
> 60
> 60

Now you've got me confused, but i least i know what output you are 
expecting. Why the LET and where does 20 come from? and What is the 
format statement supposed to do if this is the desired output?

> (I understand that the second 60 printed is the result of
> the evaluation of the (print ..) in the line calling the macro,
> and the first should be the result of the
> print function in the argument supplied by the caller).

Well, actually i'm not sure if you do :). A macro expands to sexps, so 
let us expand your macro above :

CL-USER> (macroexpand-1 '(my-list 30 45 (print 60)))
(LET ((X 20))
   45
   (PRINT 60))

Lisp returns the value of the last form evaluated. In this case, you are 
not using X (you should get a warning about this), and 45 simply 
evaluates to itself, with no side effects, so basically this form is 
that same as (print 60), which is basically the same as 60, only with 
the side effect of printing the number to a stream as well as returning it.

if you are evaluating the form  "(print (my-list 30 45 (print 60)))" 
using the definition above, you should see 3 '60's printed. I don't 
think what is happening is what you think is happening. :)

once the macro is expanded, your form looks like this:

(print (LET ((X 20))
   45
   (PRINT 60)))

if you read the CLHS entry for PRINT 
(http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_writecm_p_rintcm_princ.html)
you'll find that PRINT evaluates its argument prints it to a stream 
(which is *standard-output* by default), and then returns the result. 
So, if we ignore what is printed to the stream :

(let ((*standard-output* (make-string-output-stream)))
	   (print (my-list 30 45 (print 60 ))))

We see that your form returns the number 60, because your form is 
essentialy reduced to:

(print (print 60))

which, ignoring the side-effects on the stream, is the same as:

(print 60)

which , again ignoring the side-effects for illustrative purposes, is 
the same as:

60

> 
> --------------------------
> 4. However, if I change the macro to:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(let ((x 20)),@b) (print 42))
> 
> Then I get:
> 42
> 42

ok, this is an easy one. Remeber that defmacro only takes one form, so 
your compiler is throwing away your first two forms. PRINT is not 
quoted, so it is evaluated at macroexpand time. since you are probably 
doing this at the repl, it seems that you are seeing this result, but 
this macro really just expands to the number 42, with the PRINT 
happening when the macro is expanded. try the following to see what i mean:

CL-USER> (lambda ()
	   (my-list 30 45 (print 60)))

42
#<FUNCTION (LAMBDA ()) {9BEEAFD}>
CL-USER> (funcall *)
42
CL-USER>

The first 42 is printed when the macro is expanded, in this case when 
defining the function. the second 42 is the return value of the 
function, which is this case is simply the expansion of the macro, which 
is 42.
> --------------------------
> My first question is why I can't use `,@b, nor `(,@b) (see #1,
> #2 and #3 above). How else would I backquote a form argument to
> a macro without having to have a spurious (let ...)?

I'm not sure what it is you are trying to achieve here, so this question 
makes no sense to me, although i suspect you may be looking for PROGN.


> My second question is because I dont understand why the
> "(print 60)" does not get executed in #4 above. I feel (wrongly,
> I know) that the "(print 60)" supplied by the macro caller should
> get executed *as well as* the "(print 42)" in the macro form.

The compiler is throwing that form away, so nothing is ever executed.

> I apologise in advance for possibly stupid questions, but have
> not found the answer to these questions in the online "Practical
> Lisp" (Paul Graham), nor in the lisp tutorial that came with gnu
> clisp, nor in the online book "Successfull Lisp" (David Lamkins).

"Practical Common Lisp" was written by Peter Seibel. Paul Graham has 
written two books concerning lisp as well, "On Lisp" and "Ansi Common 
Lisp".

As i mentioned at the beginning of this post, you should probably wait 
until you have a grasp on the evaluation semantics of CL before trying 
to learn how macros work, but i hope this was of some help to you.

drewc


> I would also like to apologise if this question is in the cll faq
> (Could someone point me to that, please?).
> 
> tia
> L. K. Manickum
> 


-- 
Drew Crampsie
drewc at tech dot coop
"Never mind the bollocks -- here's the sexp's tools."
	-- Karl A. Krueger on comp.lang.lisp
From: M Jared Finder
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <JbWdnfMhm6a_loLeRVn-rA@speakeasy.net>
(remember (help lisp)) wrote:
> Hi all,
> This is my first post to cll, forgive me if I
> break any etiqutte(sp?).
> 
> Long story short, I am teaching myself Lisp
> (and have already heard all the jokes about having
> a fool for a teacher and/or a student :-) and
> have gotten stuck on something that, to me,
> does not make sense.
> 
> I have a macro that gets called like this:
> 
> (print (my-list 30 45 (print 60)))

It's important to realize that Lisp macro-functions act just like normal 
functions but at a different time.  Instead of acting on runtime values, 
a Lisp macro acts on the structure of your source code.  Other than 
that, there is *no difference*, a macro-function follows the exact same 
rules as a normal function.

When writing normal functions, your best friend is the function eval, 
which is built into the REPL (read-EVAL-print-loop).  When writing 
macro-functions, instead of using eval, you want to use macroexpand-1 
and macroexpand.  These functions let you see the expansion of your 
macro, so you can see if it really works correctly.

(Macroexpand returns two values, the expanded form, and if it performed 
any expansion.  I'm going to only show the first value, as that is 
usually the only interesting one.)

(And as an aside, has anyone ever written an eval-1 function, that acts 
similar to macroexpand-1, but on runtime values?)

> --------------------------
> 1. If a have the macro defined like so:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `,@b)
> 
> Then my lisp implementation (gnu clisp) gives me:
> 
> *** - READ: the syntax `,@form is undefined behaviour

`,@b makes no sense.  ,@ is for splicing a list into the containing 
list, as in `(progn ,@b).  With `,@ there is no containing list!

> --------------------------
> 2. If the macro is defined like this:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(,@b))
> 
> Then my lisp implementation gives me:
> 
> *** - EVAL: 45 is not a function name

CL-USER> (macroexpand-1 '(my-list 30 45 (print 60)))
(45 (PRINT 60))

Do you see why the compiler wants 45 to be a function name?

> 
> --------------------------
> 3. If my macro is defined as:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(let ((x 20)),@b))
> 
> Then my lisp implementation seems to give the correct result:
> 60
> 60
> 
> (I understand that the second 60 printed is the result of
> the evaluation of the (print ..) in the line calling the macro,
> and the first should be the result of the
> print function in the argument supplied by the caller).

CL-USER> (macroexpand-1 '(my-list 30 45 (print 60)))
(LET ((X 20))
   45
   (PRINT 60))

Do you see why that fixed it?  But there's a much better operator to use 
in this case, progn.

> --------------------------
> 4. However, if I change the macro to:
> 
> (defmacro my-list (a &body b)
>  `(format t "~a" ,a)
>   `(let ((x 20)),@b) (print 42))
> 
> Then I get:
> 42
> 42

CL-USER> (macroexpand-1 '(my-list 30 45 (print 60)))
42

Here the macro expanded the form (my-list 30 45 (print 60)) into the 
number 42.  Do you see why?

   -- MJF
From: Paul Dietz
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <431F3783.6080100@motorola.com>
M Jared Finder wrote:

> It's important to realize that Lisp macro-functions act just like normal 
> functions but at a different time.  Instead of acting on runtime values, 
> a Lisp macro acts on the structure of your source code.  Other than 
> that, there is *no difference*, a macro-function follows the exact same 
> rules as a normal function.

Well, not exactly the same.  Macro lambda lists have &environment and
&body arguments, and also destructuring.

	Paul
From: Thomas F. Burdick
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <xcvhdcwkklm.fsf@conquest.OCF.Berkeley.EDU>
Paul Dietz <············@motorola.com> writes:

> M Jared Finder wrote:
> 
> > It's important to realize that Lisp macro-functions act just like normal 
> > functions but at a different time.  Instead of acting on runtime values, 
> > a Lisp macro acts on the structure of your source code.  Other than 
> > that, there is *no difference*, a macro-function follows the exact same 
> > rules as a normal function.
> 
> Well, not exactly the same.  Macro lambda lists have &environment and
> &body arguments, and also destructuring.

That's all well and good, but that's just a syntactic convenience from
defmacro.  macro-functions are still just normal functions:

  (setf (macro-function 'noise)
  	(lambda (form env)
  	  (cons 'list
  		(if (macroexpand '(be-quiet) env)
  		    (cdr form)
  		    (loop for x in (cdr form)
  			  collect '(quote noise) collect x)))))
  
  (setf (macro-function 'be-quiet) (constantly nil))
  
  (noise 1 2 3)
  => (noise 1 noise 2 noise 3)
  
  (macrolet ((be-quiet () t))
    (noise 1 2 3))
  => (1 2 3)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Thomas A. Russ
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <ymik6hsepow.fsf@sevak.isi.edu>
There are other replies which go into more of the details.

The high level point that I want to underscore is the fundamental
difference between macros and functions in Common Lisp.  That difference
is that functions return values (in the sense of something you wanted to
have computed) whereas macros return code (i.e., some program that will
then be evaluated to produce the value you want to have computed).

The process of creating macros varies with the programmer, but what I
usually like to do is to start with a concrete bit of program that I
want to have produced and then take bits out of it to turn it into a
template which is then filled in by macro arguments (and computations
based on those arguments).

If you want an interesting excercise in macro writing, then I would
suggest writing a simplified version of the DEFSTRUCT form.  It would
have the following syntax:
   (my-defstruct  <name>
       <slot-spec>*)

where <name> is just a symbol and
      <slot-spec> is either <slot-name> or (<slot-name> <value>)
      where <slot-name> is a symbol and <value> is any lisp expression.

The code produced by MY-DEFSTRUCT will be a set of functions with the
names MAKE-<name> which creates a new object and GET-<slotname> and
SET-<slotname> functions for getting and setting slot values.  For extra
fun you can also try to figure out how to write an IS-<name> function
that will tell you if a given object is a <name> structure.

This will give you a nice appreciation for what you can do with Common
Lisp macros.  It will show the power of being able to use Lisp to help
compute what the expansion should be.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: (remember (help lisp))
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <1126189382.421485.63920@o13g2000cwo.googlegroups.com>
(remember (help lisp)) wrote:

<snipped previous request for help>

Hi all

I would like to thank all those who replied; thank you for your
(almost certainly) valuable time in answering my questions.

I apologise that my original post had an error in it, and I was not
able to see the error until I read all the responses today (google
groups dont show up the posting you just made): I meant to
have :
   (print (my-list 30 (print 60)))

and not:
   (print (my-list 30 45 (print 60)))

First, let me try to answer a few questions which some of
you asked:

   1. The expected result:
      I had wanted the form that I passed in as a macro
      argument to be evaluated.

   2. The LET and the 20:
      This was a spurious LET which made the expected result
      come out seeming correct. I did not want the LET, but
      by experimenting discovered that I got a seemingly
      correct result; I posted asking for help because I felt
      that there was an error in my logic (and I was correct
      in that, at least:-).

   3. Practical Common Lisp is indeed written by Peter Siebel.
      Apologies for the mis-citation.

And, yes, I think I get it now; I knew that macros will
expand (as opposed to functions) with the parameters being
inserted in, but:
a) I was under the impression that &body parameters had to
   use ,@ to "insert" the parameter into that point of the macro
   (I now know about splicing, thank you:-); Am I correct in
   assuming that commas are only significant when in a
   backquoted form?

b) I was incorrect in assuming that a macro could be composed
   of many forms; I now know that only a single form is allowed
   (hence my error in #4 in OP) much like the (if...) form. Therefore
   my macros, if they contain multiple forms, must use a PROGN
   (like I do with (if...)) in order to have all the forms
   (eventually) evaluated and not discarded.


Am I making any errors in those above two statements? Did I grab
the wrong end of the stick?

Finally, the simplified my-defstruct macro: After a quick search
online, I've found out what a struct is :-).

I've tried starting with something like this (I experiment a lot!):

   (defun (make-symbol (concatenate 'string '"make-" "foo")) (arg1)
    (print arg1))

But clisp did not like that: the complaint (IIRC) was that it needs
a symbol and that (make-symbol ...) was not a symbol.

How do I generate a symbol for use in a defun? 

tia
L. K. Manickum
From: M Jared Finder
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <uqqdneVcwNik_b3eRVn-pg@speakeasy.net>
(remember (help lisp)) wrote:
> (remember (help lisp)) wrote:
> 
> <snipped previous request for help>
> 
> Hi all
> 
> I would like to thank all those who replied; thank you for your
> (almost certainly) valuable time in answering my questions.
> 
> I apologise that my original post had an error in it, and I was not
> able to see the error until I read all the responses today (google
> groups dont show up the posting you just made): I meant to
> have :
>    (print (my-list 30 (print 60)))
> 
> and not:
>    (print (my-list 30 45 (print 60)))
> 
> First, let me try to answer a few questions which some of
> you asked:
> 
>    1. The expected result:
>       I had wanted the form that I passed in as a macro
>       argument to be evaluated.
> 
>    2. The LET and the 20:
>       This was a spurious LET which made the expected result
>       come out seeming correct. I did not want the LET, but
>       by experimenting discovered that I got a seemingly
>       correct result; I posted asking for help because I felt
>       that there was an error in my logic (and I was correct
>       in that, at least:-).
> 
>    3. Practical Common Lisp is indeed written by Peter Siebel.
>       Apologies for the mis-citation.
> 
> And, yes, I think I get it now; I knew that macros will
> expand (as opposed to functions) with the parameters being
> inserted in, but:
> a) I was under the impression that &body parameters had to
>    use ,@ to "insert" the parameter into that point of the macro
>    (I now know about splicing, thank you:-); Am I correct in
>    assuming that commas are only significant when in a
>    backquoted form?
> 
> b) I was incorrect in assuming that a macro could be composed
>    of many forms; I now know that only a single form is allowed
>    (hence my error in #4 in OP) much like the (if...) form. Therefore
>    my macros, if they contain multiple forms, must use a PROGN
>    (like I do with (if...)) in order to have all the forms
>    (eventually) evaluated and not discarded.
> 
> Am I making any errors in those above two statements? Did I grab
> the wrong end of the stick?

You still don't understand.  A macro-function is *just like* a normal 
function, except it runs at a different time.  There are some minor 
differences at the parameter level, which I suggest you ignore.  When 
you feel comfortable writing macros using just &optional, &key, and 
&rest parameters, you can start learning about &body, &whole, and friends.

Think of ,@ as serving a similar purpose to apply.  Most macros and 
functions don't take their parameters bundled up into a list, so you 
need some easy way to un-bundle a list's elements into some other container.

b) is completely wrong.  A macro can have as many forms as you want. 
And just like a normal function, it returns the value of the last form.

> Finally, the simplified my-defstruct macro: After a quick search
> online, I've found out what a struct is :-).
> 
> I've tried starting with something like this (I experiment a lot!):
> 
>    (defun (make-symbol (concatenate 'string '"make-" "foo")) (arg1)
>     (print arg1))
> 
> But clisp did not like that: the complaint (IIRC) was that it needs
> a symbol and that (make-symbol ...) was not a symbol.
> 
> How do I generate a symbol for use in a defun? 

You've got the right idea, but there's something wrong in your code. 
Ask yourself this:

What did macroexpand-1 return when applied to my macro?
Do I know why macroexpand-1 returned that value?
Do I know what to change to make the value correct?

   -- MJF
From: Barry Margolin
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <barmar-28F5FF.22494408092005@comcast.dca.giganews.com>
In article <······················@speakeasy.net>,
 M Jared Finder <·····@hpalace.com> wrote:

> b) is completely wrong.  A macro can have as many forms as you want. 
> And just like a normal function, it returns the value of the last form.

While they *can*, it would be quite unusual.  So if you find yourself 
creating a macro with multiple forms, you're probably doing something 
wrong.

The important thing to understand is that macros are normally only used 
for their return value.  Any forms preceding the last one are only 
executed for their side effect, just like in a normal function, but 
there's rarely a reason for macros to have side effects.

There are exceptions, though.  The implementation-provided DEFUN macro 
might have some compile-time side effects to update internal tables 
(like the one used by the compiler to warn about calls to undefined 
functions, so it would know that this function has been defined).

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: M Jared Finder
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <1bednVIkyKX8hrzeRVn-hg@speakeasy.net>
Barry Margolin wrote:
> In article <······················@speakeasy.net>,
>  M Jared Finder <·····@hpalace.com> wrote:
> 
> 
>>b) is completely wrong.  A macro can have as many forms as you want. 
>>And just like a normal function, it returns the value of the last form.
> 
> While they *can*, it would be quite unusual.  So if you find yourself 
> creating a macro with multiple forms, you're probably doing something 
> wrong.
> 
> The important thing to understand is that macros are normally only used 
> for their return value.  Any forms preceding the last one are only 
> executed for their side effect, just like in a normal function, but 
> there's rarely a reason for macros to have side effects.

Or parts of the macro is written procedurally.

This comes up when the macro has two forms, a simple form and a complete 
form.  I find myself making the first step in the macro something like:

(when (simple-form-p sub-form)
   (setf sub-form (simple-form->complete-form sub-form)))

Yes, I could do that with a let, but I find setf here to be *much* clearer.

   -- MJF
From: Peter Seibel
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <m2vf1b545b.fsf@gigamonkeys.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <······················@speakeasy.net>,
>  M Jared Finder <·····@hpalace.com> wrote:
>
>> b) is completely wrong.  A macro can have as many forms as you want. 
>> And just like a normal function, it returns the value of the last form.
>
> While they *can*, it would be quite unusual.  So if you find yourself 
> creating a macro with multiple forms, you're probably doing something 
> wrong.
>
> The important thing to understand is that macros are normally only used 
> for their return value.  Any forms preceding the last one are only 
> executed for their side effect, just like in a normal function, but 
> there's rarely a reason for macros to have side effects.
>
> There are exceptions, though.  The implementation-provided DEFUN macro 
> might have some compile-time side effects to update internal tables 
> (like the one used by the compiler to warn about calls to undefined 
> functions, so it would know that this function has been defined).

But even in cases like that, shouldn't macros typically achieve their
side-effects by expanding into a form containing an EVAL-WHEN? I
suppose implementation-defined macros, being part of the
implementation, could get away with skipping the EVAL-WHEN, knowing
how the implementation works. But user-defined macros that need to
have compile-time side-effects should achive them via EVAL-WHEN forms,
no?

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Barry Margolin
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <barmar-97CA13.23230808092005@comcast.dca.giganews.com>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Barry Margolin <······@alum.mit.edu> writes:
> 
> > In article <······················@speakeasy.net>,
> >  M Jared Finder <·····@hpalace.com> wrote:
> >
> >> b) is completely wrong.  A macro can have as many forms as you want. 
> >> And just like a normal function, it returns the value of the last form.
> >
> > While they *can*, it would be quite unusual.  So if you find yourself 
> > creating a macro with multiple forms, you're probably doing something 
> > wrong.
> >
> > The important thing to understand is that macros are normally only used 
> > for their return value.  Any forms preceding the last one are only 
> > executed for their side effect, just like in a normal function, but 
> > there's rarely a reason for macros to have side effects.
> >
> > There are exceptions, though.  The implementation-provided DEFUN macro 
> > might have some compile-time side effects to update internal tables 
> > (like the one used by the compiler to warn about calls to undefined 
> > functions, so it would know that this function has been defined).
> 
> But even in cases like that, shouldn't macros typically achieve their
> side-effects by expanding into a form containing an EVAL-WHEN? I
> suppose implementation-defined macros, being part of the
> implementation, could get away with skipping the EVAL-WHEN, knowing
> how the implementation works. But user-defined macros that need to
> have compile-time side-effects should achive them via EVAL-WHEN forms,
> no?

The EVAL-WHEN mechanism will only work if the call is at top-level.  If 
it should have compile-time side effects even when the macro call is in 
an embedded expression, it must be done using a side effect in the macro 
function itself, not the expansion.

That's the reason why the keywords in EVAL-WHEN were changed from 
Maclisp's COMPILE and LOAD to :COMPILE-TOPLEVEL and :LOAD-TOPLEVEL.  
Maclisp users sometimes found it confusing that (EVAL-WHEN (COMPILE) 
...) didn't always perform the side effects at compile time.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Thomas A. Russ
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <ymifysfe0bs.fsf@sevak.isi.edu>
"(remember (help lisp))" <····@webmail.co.za> writes:
> Finally, the simplified my-defstruct macro: After a quick search
> online, I've found out what a struct is :-).
> 
> I've tried starting with something like this (I experiment a lot!):
> 
>    (defun (make-symbol (concatenate 'string '"make-" "foo")) (arg1)
>     (print arg1))
> 
> But clisp did not like that: the complaint (IIRC) was that it needs
> a symbol and that (make-symbol ...) was not a symbol.

The form (make-symbol ...) itself is not a symbol.  Only when it gets
evaluated does it return a symbol.  Also, remember that DEFUN itself is
a macro which does not evaluate its arguments.  Otherwise you would
have to write the awkward form 
    (DEFUN 'FOO '(A B) '(+ A B)) insted of (DEFUN FOO (A B) (+ A B))

> How do I generate a symbol for use in a defun? 

The key is to do this when you are creating the DEFUN form, which really
means you will wnat to do it inside a macro body.

But you don't really want MAKE-SYMBOL, because it creates uninterned
symbols.  You will want to use INTERN instead.  Here you should make a
digression to learn about interning symbols.  The quick summary is that
unless you intern a symbol, you can't look it up by name.  The practical
upshot is that if you use MAKE-SYMBOL, then you won't be able to invoke
the function, because you can't get the same symbol object you used to
name the function to invoke it.

Contrast
   (eq (make-symbol "FOO-BAR") (make-symbol "FOO-BAR"))
with
   (eq (intern "FOO-BAR") (intern "FOO-BAR"))

OK.  So what you want to do is have a form something like this inside
your macro body:

    `(defun ,(intern (concatenate 'string "MAKE-" "FOO")) (ARG1)
        (PRINT ARG1))

where you use backquote and "," to force the evaluation of the INTERN
function call.

At this point it may also be helpful to review (or learn about) the way
the Lisp reader does case conversion before it interns symbols that it
reads.  In particular, note the difference between the way the following
symbols print:
    (INTERN "foo")    =>   |foo|
    (INTERN "FOO")    =>   FOO

and note the result of

    (eq (intern "foo") (intern "FOO"))


> 
> tia
> L. K. Manickum
> 

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: (remember (help lisp))
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <1126270802.093000.257090@g44g2000cwa.googlegroups.com>
(remember (help lisp)) wrote:
> (remember (help lisp)) wrote:
>
> <snipped previous request for help>
>

<snipped reply to original request for help>

Hello all

Thanks again for the help. I dont understand fully, it seems.

One poster says that a macro may have only a single form, and that
I should use (progn...) if I want more than the last form evaluated.

Another poster said that macros *can* have more than a single form.

The book "Practical Common Lisp" says that I may only have a single
form in a macro (chapter 24: parsing binary files - "Also, because
a macro must expand into a single form, you need to wrap some form
around the DEFCLASS and DEFMETHOD") *and* that a macro consists
of more than 1 lisp expression (chapter 8: Macros: defining your
own - "Like a function, a macro consists of a name, a parameter
list, an optional documentation string, and a body of Lisp
expressions").

I suppose that that means that "a body of lisp expressions" is only
a single form (the text in that chapter does not make it clear that
only a single form is needed)?

Anyway, to clear up, I assumed (from the replies) that a macro
can have many forms, but will only return (or is it evalute?) the
final form when it is expanded?

To move on to the my-defstruct expedition:

After a couple of searches on the net, I found that "interning"
is "the act of putting a symbol into a package" (The Complete Idiots
Guide to Common Lisp Packages,
http://www.flownet.com/gat/packages.pdf).

The Hyperspec that was kindly pointed out by someone else here seems
to support that statement.

Make-symbol, OTOH, "returns a fresh, uninterned symbol" (the
hyperspec).

I've tried interning a symbol, but I dont see any way to get at it
after interning it. e.g.

--------------------------
[318]> (defmacro fubar (arg1)
        `(defun
           ,(intern (concatenate 'string '"make-" (symbol-name
`,arg1)))
           (arg2)
         (print arg2)))
FUBAR
[319]> (macroexpand-1 '(fubar man))
        (DEFUN |make-MAN| (ARG2) (PRINT ARG2)) ;
T
[320]> (fubar man)
|make-MAN|
[321]> (make-MAN "hello world")

** - Continuable Error
EVAL: undefined function MAKE-MAN
If you continue (by typing 'continue'): Retry
The following restarts are also available:
STORE-VALUE    :R1      You may input a new value for (FDEFINITION
'MAKE-MAN).
USE-VALUE      :R2      You may input a value to be used instead of
(FDEFINITION 'MAKE-MAN).

Break 1 [322]>


???

So how do I now call the function that the macro generated?
And what is make-symbol actually used for if I cannot get at
the symbol that it makes?

tia
L. K. Manickum
From: M Jared Finder
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <WNednZM3qufSMrzeRVn-tw@speakeasy.net>
(remember (help lisp)) wrote:

> Anyway, to clear up, I assumed (from the replies) that a macro
> can have many forms, but will only return (or is it evalute?) the
> final form when it is expanded?

That is exactly correct; a macro-function can have many forms, but (like 
a normal function) only the value of the final form is used.  That is 
the macro-function's expansion.

In particular, this disallows you from returning multiple expansions 
using values.

> I've tried interning a symbol, but I dont see any way to get at it
> after interning it. e.g.
> 
> --------------------------
> [318]> (defmacro fubar (arg1)
>         `(defun
>            ,(intern (concatenate 'string '"make-" (symbol-name
> `,arg1)))
>            (arg2)
>          (print arg2)))
> FUBAR
> [319]> (macroexpand-1 '(fubar man))
>         (DEFUN |make-MAN| (ARG2) (PRINT ARG2)) ;
> T
> [320]> (fubar man)
> |make-MAN|
> [321]> (make-MAN "hello world")

Common Lisp is not case-insensitive, it is case normalizing.  You should 
change "make-" to "MAKE-", as Common Lisp upcases all symbol names by 
default.  The bars appeared around make-MAN to show that the symbol's 
name was not all uppercase.

An even better solution would be to allow the reader to do that 
conversion for you:

(intern (concatenate 'string (symbol-name :make-) (symbol-name arg1)))

I find myself doing that a lot, so I wrote a symbol-concatenate function 
that creates an interned symbol by concatenating the names of any amount 
of symbols.

   -- MJF
From: Marco Antoniotti
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <vrjUe.3$pa3.394@typhoon.nyu.edu>
M Jared Finder wrote:
> An even better solution would be to allow the reader to do that 
> conversion for you:
> 
> (intern (concatenate 'string (symbol-name :make-) (symbol-name arg1)))
> 
> I find myself doing that a lot, so I wrote a symbol-concatenate function 
> that creates an interned symbol by concatenating the names of any amount 
> of symbols.
> 

This way you risk dumping a lot of symbols in the KEYWORD package.  A 
solution that has the chance of being more memory thrifty is

(intern (concatenate 'string (symbol-name '#:make-) (symbol-name arg1)) 
package)

Cheers
--
marco
From: Pascal Bourguignon
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <87u0gu9pee.fsf@thalassa.informatimago.com>
M Jared Finder <·····@hpalace.com> writes:
> Common Lisp is not case-insensitive, it is case normalizing.  You
> should change "make-" to "MAKE-", as Common Lisp upcases all symbol
> names by default.  The bars appeared around make-MAN to show that the
> symbol's name was not all uppercase.
>
> An even better solution would be to allow the reader to do that
> conversion for you:
>
> (intern (concatenate 'string (symbol-name :make-) (symbol-name arg1)))
          (format nil ··@{~A~}" :fun- "HELLO" '- 12) --> "FUN-HELLO-12"

> I find myself doing that a lot, so I wrote a symbol-concatenate
> function that creates an interned symbol by concatenating the names of
> any amount of symbols.
>
>    -- MJF

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Wanna go outside.
Oh, no! Help! I got outside!
Let me back inside!
From: Raffael Cavallaro
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <2005090910224543658%raffaelcavallaro@pasdespamsilvousplaitmaccom>
On 2005-09-09 09:00:02 -0400, "(remember (help lisp))" 
<····@webmail.co.za> said:

> [318]> (defmacro fubar (arg1)
>         `(defun
>            ,(intern (concatenate 'string '"make-" (symbol-name
> `,arg1)))
>            (arg2)
>          (print arg2)))
> FUBAR
> [319]> (macroexpand-1 '(fubar man))
>         (DEFUN |make-MAN| (ARG2) (PRINT ARG2)) ;
> T
> [320]> (fubar man)
> |make-MAN|
> [321]> (make-MAN "hello world")
> 
> ** - Continuable Error
> EVAL: undefined function MAKE-MAN

Read the error carfully. Your fubar macro made a function named |make-MAN|.
That is, lowercase "make" hyphen uppercase "MAN."

I bet that (readtable-case *readtable*) returns :UPCASE in your common 
lisp at present.

You most likely called (all uppercase) MAKE-MAN because the reader is 
upcasing everything that is not escaped by vertical bars.

try this and see what you get:

(|make-MAN| "hello world")

This tells the reader to leave make-MAN exactly as you typed it.

You should probably write your macro to prepend the string "MAKE-" not 
the string "make-"

(defmacro fubar (arg1)
        `(defun
           ,(intern (concatenate 'string '"MAKE-" (symbol-name
`,arg1)))
           (arg2)
         (print arg2)))

regards
From: Pascal Bourguignon
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <87br32b9uv.fsf@thalassa.informatimago.com>
"(remember (help lisp))" <····@webmail.co.za> writes:
> Thanks again for the help. I dont understand fully, it seems.
>
> One poster says that a macro may have only a single form, and that
> I should use (progn...) if I want more than the last form evaluated.
>
> Another poster said that macros *can* have more than a single form.
> [...]
> I suppose that that means that "a body of lisp expressions" is only
> a single form (the text in that chapter does not make it clear that
> only a single form is needed)?


DEFMACRO, as DEFUN put all the forms in their bodies inside an
implicit BLOCK, (and BLOCK put them inside an implicit PROGN), so in
effect, the body of any function (or macro), consists in only one
form.  But you don't have to write the BLOCK or PROGN yourself.

To know that you only need to read CLHS.

 http://www.lispworks.com/reference/HyperSpec/Body/m_defun.htm
 http://www.lispworks.com/reference/HyperSpec/Body/m_defmac.htm
 http://www.lispworks.com/reference/HyperSpec/Body/s_block.htm
 http://www.lispworks.com/reference/HyperSpec/Body/s_progn.htm



Perhaps macros are looking more complex than they are exactly for this
false idea that the body of a macro should consist in one form.  This
is plainly false.  Instead of writting a complex backquote-comma
expression, you can simplify a lot big macros by generating separately
parts of the produced code:


(defmacro defsomething (name &rest arguments)
  (let ((name  (intern (gen-name name arguments)))
        (args  (gen-arg-list  name arguments))
        (docst (gen-docstring name arguments))
        (plist (gen-some-plist name arguments))
        (condi (gen-condition arguments))
        (bodyt (gen-body-then arguments))
        (bodye (gen-body-else arguments)))
    ;; then you can write the resulting form clearly:
    (if (some-hairy-condition arguments)
        `(progn
           (setf (gethash ',name *the-somethings*) ',plist)
           (defun ,name ,args
             ,docst
             ,bodyt))
        `(progn
           ,@(loop for (k v) on plist
                collect `(setf (get ',name ',k) ',v))
           (defun ,name ,args
             ,docst
             (if ,condi
                 ,bodyt
                 ,bodye))))))

Note how we trivially generate "several forms" encapsulating them in one PROGN.


> Anyway, to clear up, I assumed (from the replies) that a macro
> can have many forms, but will only return (or is it evalute?) the
> final form when it is expanded?

The macro function is executed.  The macro "call", the form whose car
is a macro, a symbol that has in its function slot a macro function,
is expanded.

When you execute (macroexpand '(m2 (terpri))), this is not the macro
m2 that is expanded.  This is the form (m2 (terpri)) that is macroexpanded:


[2]> (defmacro m1 (x) `(progn ,x))
M1
[3]> (defmacro m2 (x) `(m1 ,x))
M2
[4]> (macroexpand '(m2 (terpri)))
(PROGN (TERPRI)) ;
T
[5]> (macroexpand-1 '(m2 (terpri)))
(M1 (TERPRI)) ;
T


> To move on to the my-defstruct expedition:
>
> After a couple of searches on the net, I found that "interning"
> is "the act of putting a symbol into a package" (The Complete Idiots
> Guide to Common Lisp Packages,
> http://www.flownet.com/gat/packages.pdf).
>
> The Hyperspec that was kindly pointed out by someone else here seems
> to support that statement.
>
> Make-symbol, OTOH, "returns a fresh, uninterned symbol" (the
> hyperspec).
>
> I've tried interning a symbol, but I dont see any way to get at it
> after interning it. e.g.

Well, you cannot INTERN a pre-existing symbol.  But you can IMPORT it.

INTERN takes a string. So you could create a new symbol with the same name,
but the result wouldn't be EQL to the original uninterned symbol.

(let ((homeless (make-symbol "HOBO")))
  (setf (symbol-value homeless) "Joe Cheap")
  (import homeless *package*)
  ;; Note 1: it's important not to have the reader read a symbol named HOBO 
  ;; in the current package before executing this IMPORT, or a conflict
  ;; would occur (you could use SHADOW to prevent the conflict).
  ;; Note 2: IMPORT is charitable: 
  ;;   If any symbol to be imported has no home package (i.e., (symbol-package
  ;;   symbol) =>  nil), import sets the home package of the symbol to package.
  )

(print (list (symbol-package 'HOBO) (symbol-value 'HOBO)))

  

> [318]> (defmacro fubar (arg1)
>         `(defun
>            ,(intern (concatenate 'string '"make-" (symbol-name
> `,arg1)))
>            (arg2)
>          (print arg2)))
> FUBAR
> [319]> (macroexpand-1 '(fubar man))
>         (DEFUN |make-MAN| (ARG2) (PRINT ARG2)) ;
> T
> [320]> (fubar man)
> |make-MAN|
> [321]> (make-MAN "hello world")
>
> ** - Continuable Error
> EVAL: undefined function MAKE-MAN
> If you continue (by typing 'continue'): Retry
> The following restarts are also available:
> STORE-VALUE    :R1      You may input a new value for (FDEFINITION
> 'MAKE-MAN).
> USE-VALUE      :R2      You may input a value to be used instead of
> (FDEFINITION 'MAKE-MAN).

Now, this is something completely different.  It has  alreaady been
mentionned that the lisp reader pre-processes the symbol names before
interning them, according to (READTABLE-CASE *READTABLE*).  The
default value is :UPCASE, which makes it upcase all the names before
interning them

(|STRING/=| "make-MAN" "MAKE-MAN") 
so obviously: (|NOT| (|EQ| (|INTERN| "make-MAN") (|INTERN| "MAKE-MAN")))
that is:      (|NOT| (|EQ| '|make-MAN| '|MAKE-MAN|))

>
> So how do I now call the function that the macro generated?

(|make-MAN| ...)

> And what is make-symbol actually used for if I cannot get at
> the symbol that it makes?

Symbols are structures like:

(defstruct symbol
    (name      ""  :type string)
    (package   nil :type (or null package))
    (value     nil :type t)
    (function  nil :type (or null function))
    (plist     nil :type list))

These structures can be useful in some applications in their own
right.  For example, in NLP processing you can attach to each tocken a
function and some properties:

(make-symbol :name "cat" :function (lambda () (print "Miaou!"))
             :plist '(:word-type noun :sex neutral :number singular
                      :definition "A sort of small mamal carnivore"))




Of course, a nice use is to store information and meta information
about a program. 

For example, when you write:

(defparameter *animals* '(|cat| |dog| WHALE)
  "A list of symbols naming animals")

A lisp implementation could execute:

(put-in-oblist
  *package*
  (make-symbol :name "*ANIMALS*" :package *package* :value '(|cat| |dog| WHALE)
          :plist '(system:documentation "A list of symbols naming animals")))

The point being to allow introspective processing. Now you can write
higher order functions, or macros, that is, functions that take as
input other functions or forms and produce new functions or forms.



But the notion of symbol goes beyond the mere representation of
programs. They can be used to represent any kind of abstration.

That said, in modern lisps, since we can build random structures and
classes, we don't need to rely on this predefined symbol structure
(using the plist to add attibutes); we can directly define our own
structures or classes, so the relevance of symbols for treatments
other than lisp code manipulation is smaller.  

So why would you want to intern a symbol representing an abstraction
in the mind of a remote agent, when you never reference it in your
sources?  You can still manipulate it and store it in your own
data structures (lists, arrays, hashtables, etc).

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

The world will now reboot.  don't bother saving your artefacts.
From: Peter Seibel
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <m2acimkqkq.fsf@gigamonkeys.com>
"(remember (help lisp))" <····@webmail.co.za> writes:

> Thanks again for the help. I dont understand fully, it seems.
>
> One poster says that a macro may have only a single form, and that
> I should use (progn...) if I want more than the last form evaluated.
>
> Another poster said that macros *can* have more than a single form.

The problem is that "have" is not very specific. There are two ways to
look at a macro--as a function that returns a value (where the value
returned is called the "macro expansion") or as the resulting
expansion. The result of calling a macro--it's macro expansions--must
be a single form. But as a function--and like all other functions--the
body of the macro, the code that computes the value to return can
consist of as many forms as you want.

However, as is always the case with functions, absent any control-flow
altering constructs such as RETURN-FROM, the return value (i.e. the
macro expansion) is typically the result of evaluating the *last* form
in the body. And since there's little reason to have a macro have
other side effects since it runs (typically) at compile time, there's
little reason for a macro to do anything but compute is macro
expansion and return. That said, you can do this:

  (defmacro foo (&body body)
    (format t "FOO is being expanded.~%")
    `(progn
      (format t "The code generated by FOO is being run.~%")
      ,@body))

The body of the macro definition is two forms: the first FORMAT and
the backquote expression. The FORMAT is run whenever the macro is
run--whenever a (FOO ...) form is expanded and then the backquote
expression generates the return value which becomes the expansion.

> The book "Practical Common Lisp" says that I may only have a single
> form in a macro (chapter 24: parsing binary files - "Also, because a
> macro must expand into a single form, you need to wrap some form
> around the DEFCLASS and DEFMETHOD") *and* that a macro consists of
> more than 1 lisp expression (chapter 8: Macros: defining your own -
> "Like a function, a macro consists of a name, a parameter list, an
> optional documentation string, and a body of Lisp expressions").

Note the wording. A macro must "expand into" a single form.

> I suppose that that means that "a body of lisp expressions" is only
> a single form (the text in that chapter does not make it clear that
> only a single form is needed)?

No, it's zero or more expressions, just like in a function.

> Anyway, to clear up, I assumed (from the replies) that a macro
> can have many forms, but will only return (or is it evalute?) the
> final form when it is expanded?

Return.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Barry Margolin
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <barmar-753ACD.02130810092005@comcast.dca.giganews.com>
In article <························@g44g2000cwa.googlegroups.com>,
 "(remember (help lisp))" <····@webmail.co.za> wrote:

> One poster says that a macro may have only a single form, and that
> I should use (progn...) if I want more than the last form evaluated.
> 
> Another poster said that macros *can* have more than a single form.
> 
> The book "Practical Common Lisp" says that I may only have a single
> form in a macro (chapter 24: parsing binary files - "Also, because
> a macro must expand into a single form

A macro may only *expand into* a single form.  But it may *contain* 
multiple forms that compute that expansion.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: goose
Subject: Re: Macro misunderstandings: 5 hours experience with lisp
Date: 
Message-ID: <dfvdbs$2hk$1@ctb-nnrp2.saix.net>
(remember (help lisp)) wrote:
> (remember (help lisp)) wrote:
> 
>>(remember (help lisp)) wrote:
>>
>><snipped previous request for help>
>>
> 
> <snipped reply to original request for help>
> 

<snipped yet again>

<slightly ot>
Thank you all; I'm better informed now :-)

Please ignore my name-change from "(remember ...)"; from
now on I will post with this user-id as I am back at home.

</ot>

I've not had any problems with my toy functions, only
with my macros (which seem to prove the bigger difference
between the two). I *mostly* get it now (am too nervous
to say that I get it, in case I stumble across more
problems)

I have, for the moment, stopped all my lisp exploits
as my exams are coming up, and will resume once again
in mid-november once exams are over; be assured that I will
be back to pick your brains again ;-)

thanks for all the help
L. K. Manickum