Subject: [clisp-list] macro problem

From: Thomas Torsney-Weir <[email-masked]>
Date: Mon Aug 11 19:41:02 2003

This is really a general lisp question, but anyway.

Can someone explain why macros can't destructure lists of more than 2 
items?  So I can't do this:

[148]> (defmacro broken-mac ((a b c)) `(,a ,b ,c))
BROKEN-MAC
[149]> (broken-mac '(1 2 3))
*** - EVAL: too many parameters for special operator QUOTE: (QUOTE (1 2 
3) NIL)

But this works?
[151]> (defmacro ok-mac ((a b)) `(,a ,b))
OK-MAC
[152]> (ok-mac '(1 2))
(1 2)

It doesn't make any sense to me.  I wrote a version as a function with 
destructuring-bind and that works as expected.

---

From: David Morse <[email-masked]>
Date: Mon Aug 11 20:29:11 2003

> [151]> (defmacro ok-mac ((a b)) `(,a ,b))

Short answer: you probably want to call broken-mac without the quote 
character before the first argument.

Long answer:

ok-mac is designed to be called with two "sub-arguments" in the first 
argument.  Here you're calling it with the first sub-argument QUOTE and 
the second sub-argument (1 2).  Thus after macroexpansion you send 
(QUOTE (1 2)) to lisp.  That gets evaluated and you end up with a list 
whose first elt is 1 and second elt is 2.  No errors.

borken-mac is designed to be called with three "sub-arguments" in the 
first argument.  Here you're calling it with the first sub-argument 
QUOTE, the second sub-argument (1 2 3), and no third argument (seems to 
default to nil, though I suspect it should error).  Thus after 
macroexpansion you send (QUOTE (1 2 3) nil) to lisp.  Quote is supposed 
to take exactly 1 argument, not two, so now you know what "too many 
parameters for special operator QUOTE" is trying to tell you.  The macro 
is doing its job, sort of, and transforming its input.  Its just that 
output is not executable lisp, and thus doesn't survive the ensuing 
evaluation.

---

From: Pascal Bourguignon <[email-masked]>
Date: Mon Aug 11 22:20:02 2003

> destructuring-bind and that works as expected.

Use macroexpand and see what happens:

[10]> (defmacro broken-mac ((a b c)) `(,a ,b ,c))
BROKEN-MAC
[11]> (macroexpand '(broken-mac '(1 2 3)))
(QUOTE (1 2 3) NIL) ;
T
[12]> (defmacro ok-mac ((a b)) `(,a ,b))
OK-MAC
[13]> (macroexpand '(ok-mac '(1 2)))
'(1 2) ;
T
[14]> (macroexpand '(ok-mac '(1 2 3)))
'(1 2 3) ;
T
[15]> (macroexpand '(broken-mac '(1 2)))
(QUOTE (1 2) NIL) ;
T
[16]> (macroexpand '(broken-mac '(1 2 3 4)))
(QUOTE (1 2 3 4) NIL) ;
T

Or you could print argument values from the macro:

[17]> (defmacro broken-mac ((a b c)) (format t "a=~S~%b=~S~%c=~S~%" a b c) `(,a ,b ,c))
BROKEN-MAC
[18]>  (broken-mac '(1 2))
a=QUOTE
b=(1 2)
c=NIL

*** - EVAL: too many parameters for special operator QUOTE: (QUOTE (1 2) NIL)
1. Break [19]> 
[20]>  (broken-mac '(1 2 3))
a=QUOTE
b=(1 2 3)
c=NIL

*** - EVAL: too many parameters for special operator QUOTE: (QUOTE (1 2 3) NIL)
1. Break [21]> 

The point is that both '(1 2 3)  and '(1 2) (and '(1 2 3 4)) are lists
of only TWO items.  The first  item is the symbol QUOTE and the second
item is the list written in the expression (1 2 3) or (1 2) (or (1 2 3
4), etc),  as revealed by the  format statement in  my redefinition of
broken-mac.

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.

---

From: Pascal Bourguignon <[email-masked]>
Date: Mon Aug 11 22:25:01 2003

> 4), etc),  as revealed by the  format statement in  my redefinition of

I should  add that the strange  behavior comes from the  fact that the
arguments  of  a  macro are  not  evalued,  like  the arguments  to  a
function.  To get the effect you  want with a macro, you would have to
write the argument without the quote:

[29]>  (broken-mac (list 2 3))
a=LIST
b=2
c=3
(2 3)
[30]>  (broken-mac (+ 2 3))
a=+
b=2
c=3
5
[31]>

---

From: Kaz Kylheku <[email-masked]>
Date: Tue Aug 12 10:22:21 2003

On Mon, 11 Aug 2003, Thomas Torsney-Weir wrote:

> Date: Mon, 11 Aug 2003 22:21:36 -0400
> From: Thomas Torsney-Weir <[email-masked]>
> To: [email-masked]
> Subject: [clisp-list] macro problem
> 

This is equivalent to (broken-mac (quote (1 2 3))).  

What's broken here, I think, is that the destructuring error is not
signaled. There are only two parameters given for the nested lambda
list (a b c).

> [151]> (defmacro ok-mac ((a b)) `(,a ,b))

This is just (ok-mac (quote (1 2))) So the A parameter is the symbol
QUOTE, and the B paramter is the list (1 2). The replacement form is
therefore (QUOTE (1 2)).

The (quote (1 2)) list is passed to the macro without being evaluated.

> destructuring-bind and that works as expected.

But functions are different. The argument expressions in a function
call are evaluated, so if you have an OK-FUNC instead of OK-MAC and you
call it like (ok-mac '(1 2)) then it just gets one argument---the list
(1 2). Moreover, the return value is not substituted into the program
and re-evaluated.

-- 
Meta-CVS: directory structure versioning; versioned symbolic links;
versioned execute permission; versioned property lists; easy branching
and merging and third party code tracking; all implemented over the
standard CVS command line client -- http://freshmeat.net/projects/mcvs

---

From: Sam Steingold <[email-masked]>
Date: Thu Aug 14 15:38:02 2003

> * In message <[email-masked]>
> * On the subject of "Re: macro problem"
> * Sent on Tue, 12 Aug 2003 10:14:01 -0700 (PDT)
> * Honorable Kaz Kylheku <[email-masked]> writes:
>

I just fixed this in the CVS.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Never trust a man who can count to 1024 on his fingers.