From: Vali
Subject: Can a macro define a macro?
Date: 
Message-ID: <1144575700.701061.215250@t31g2000cwb.googlegroups.com>
Hi,
I played around a bit at the repl and wrote the following function:

(defun powers1 (x)
	(loop for n from 1 to 5 collecting (expt x n)))

I wondered if it was possible to return the powers not as a list, but
as multiple values. That is what I came up with:

(defmacro powers (x)
	`(values ,@(loop for n from 1 to 5 collecting (expt x n))))

Next thing I tried was to define a macro that does not return the first
5 powers of x, but takes a number (say i) as argument and returns a
function (or macro) returning the first i powers of its argument.
Something like that:

(defmacro powersn (name n)
	`(defmacro ,name (x)
		(values ,@(loop for i from 1 to n collecting (expt x i)))))

Well, that does not work. Could someone give me a hint about how to do
it right?

thx,
Valentin

From: Frank Buss
Subject: Re: Can a macro define a macro?
Date: 
Message-ID: <9urutiwhgwom.ji5gjhbjjzv0$.dlg@40tude.net>
Vali wrote:

> (defmacro powersn (name n)
> 	`(defmacro ,name (x)
> 		(values ,@(loop for i from 1 to n collecting (expt x i)))))
> 
> Well, that does not work. Could someone give me a hint about how to do
> it right?

There are some backticks and commas missing:

(defmacro powersn (name n)
  `(defmacro ,name (x)
     `(values ,@(loop for i from 1 to ,n collecting (expt x i)))))

CL-USER > (powersn power5 5)
POWER5

CL-USER 6 > (power5 2)
2
4
8
16
32

CL-USER > (powersn much-more 10)
MUCH-MORE

CL-USER 9 > (much-more 3)
3
9
27
81
243
729
2187
6561
19683
59049

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Vali
Subject: Re: Can a macro define a macro?
Date: 
Message-ID: <1144577091.594631.169690@i40g2000cwc.googlegroups.com>
Well, I guess that'll take some time till I get used to these double
backticks...
Thanks alot for your fast reply!

Valentin
From: Pascal Costanza
Subject: Re: Can a macro define a macro?
Date: 
Message-ID: <49s4g7Fqc7skU1@individual.net>
Vali wrote:
> Hi,
> I played around a bit at the repl and wrote the following function:
> 
> (defun powers1 (x)
> 	(loop for n from 1 to 5 collecting (expt x n)))
> 
> I wondered if it was possible to return the powers not as a list, but
> as multiple values. That is what I came up with:
> 
> (defmacro powers (x)
> 	`(values ,@(loop for n from 1 to 5 collecting (expt x n))))

It's not a good idea to use a macro here. The part behind the ,@ is 
going to be evaluated at macroexpansion time, that is, at compile time 
in the general case. So this macro will only work when you call it with 
constant numbers. Try the following to see what I mean:

(let ((x 5)
   (powers x))

It's possible/better to write this as a function:

(defun powers (x)
   (values-list (loop for n from 1 to 5 collection (expt x n))))

> Next thing I tried was to define a macro that does not return the first
> 5 powers of x, but takes a number (say i) as argument and returns a
> function (or macro) returning the first i powers of its argument.
> Something like that:
> 
> (defmacro powersn (name n)
> 	`(defmacro ,name (x)
> 		(values ,@(loop for i from 1 to n collecting (expt x i)))))
> 
> Well, that does not work. Could someone give me a hint about how to do
> it right?

Here the fact bites you that parts of your macro will be expanded before 
they can see actual runtime values. (see above)

The following should work:

(defmacro powersn (name n)
   `(defun ,name (x)
      (values-list (loop for i from 1 to ,n collecting (expt x i)))))


BTW, you shouldn't overstress the multiple values feature. There is a 
limit on how many multiple values you can return (see 
multiple-values-limit) and it also doesn't make a lot of sense to return 
lots of multiple values. It seems that in your case it is likely that 
the caller will want to see all the return values, and then it's better 
to just return a list. Multiple values are useful when callers may want 
to ignore some of the return values, or when you have few return values.

For example, why don't you just write this?

(defun powersn (x n)
   (loop for i from to n collecting (expt x i)))


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Vali
Subject: Re: Can a macro define a macro?
Date: 
Message-ID: <1144577967.798308.213150@v46g2000cwv.googlegroups.com>
Thanks for your reply, Pascal. I was not aware of the expansion
problem. So thanks indeed for pointing that one out.
You are absolutely right: this example does not make too much sense. I
just wanted to know how to correctly mix multiple value generation and
macro code. It isn't part of any project or so, just of my attempt to
grasp some Lisp.

Valentin
From: Frode Vatvedt Fjeld
Subject: Re: Can a macro define a macro?
Date: 
Message-ID: <2hr746lb1m.fsf@vserver.cs.uit.no>
Pascal Costanza <··@p-cos.net> writes:

> (defun powers (x)
>    (values-list (loop for n from 1 to 5 collection (expt x n))))

Also remember "values" is a function, so you can do (apply #'values ..).
(Which in all likelyhood is exactly what values-list expands to anyway.)

-- 
Frode Vatvedt Fjeld
From: Tim X
Subject: Re: Can a macro define a macro?
Date: 
Message-ID: <87lkud6cn1.fsf@tiger.rapttech.com.au>
"Vali" <·····@web.de> writes:

> Hi,
> I played around a bit at the repl and wrote the following function:
>
> (defun powers1 (x)
> 	(loop for n from 1 to 5 collecting (expt x n)))
>
> I wondered if it was possible to return the powers not as a list, but
> as multiple values. That is what I came up with:
>
> (defmacro powers (x)
> 	`(values ,@(loop for n from 1 to 5 collecting (expt x n))))
>
> Next thing I tried was to define a macro that does not return the first
> 5 powers of x, but takes a number (say i) as argument and returns a
> function (or macro) returning the first i powers of its argument.
> Something like that:
>
> (defmacro powersn (name n)
> 	`(defmacro ,name (x)
> 		(values ,@(loop for i from 1 to n collecting (expt x i)))))
>
> Well, that does not work. Could someone give me a hint about how to do
> it right?
>

I'm assuming you are doing this just for experimental/learning
purposes, but just in case your not, I'd argue a macro is overkill
for this and is likely to make your code more difficult to understand
rather than easier. 

To my knowledge, there is no restriction technically from having a
macro define a macro BUT...

don't forget macros are expanded at compile time, so the expansion is
limited to what is known at compile time, which can be different to
run time. I would be concerned this could cause you some strange
results, especially when expanding things like ,@. However, I'm still
very much a newbie here as well, so I might have it completely wrong. 

From a stylistic standpoint, I can't see why you would return multiple
values rather than (lets say) a list. I prefer to use a list if you
have a list of the 'same' items, but use values when I have a specific
value, but think it might also be useful to return other information.
for exmaple, I might use values if I was returning a substring and
also thought it was good to make the index of the substring available
- to me, these are different bits of information and most of the time,
I would only be interested in the main bit of info, the substring.
However, sometimes, I might also want to see the index as well. 

Using values to return a group of related things means I'm more than
likely to need all of the values being returned, which means more
multiple value binds, which I find more untidy than just returning a
list and processing them as needed.

However, tastes vary. One of the things I like with Cl is that more
often than not, the language seems to meld nicely with how I'm
thinking about the problem and I don't need to spend heaps of effort
trying to take my incredibly brilliant and elegant idea and smash it
beyond recognition so that it fits with how some language needs to
express it. This is often a two edge sword because more often than
not, I also find once I go to express my wonderfully brilliant and
elegant idea that CL shows me its actually quite lame and stupid
within just a short time - with C++ and Java, I was able to live a
happy deluded existance for a lot longer - bliss in ignorance and all
that.

Tim
-- 
tcross (at) rapttech dot com dot au