Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question about lisp macros

54 views
Skip to first unread message

CoffeeMug

unread,
Feb 1, 2005, 5:09:38 PM2/1/05
to
I'm new to lisp (coming from an extensive C++ background) so I
apologize in advance if my questions don't make sense.

I realize that lisp macros are regular functions that are executed at
compile time. If that is the case, what happens if I bind a symbol to a
macro (not its return value, but the macro itself) and then use that
symbol to call a macro in a function? Will the macro be called at run
time as a regular function?

Also, it looks like a macro can return anything it wants. What happens
if it returns a function instead of a list? If I then use the macro in
some function, what will be the result? If a macro returns a list, it's
evident, but what about a function object?

Thanks.

Kenny Tilton

unread,
Feb 1, 2005, 5:45:10 PM2/1/05
to

CoffeeMug wrote:
> I'm new to lisp (coming from an extensive C++ background) so I
> apologize in advance if my questions don't make sense.
>
> I realize that lisp macros are regular functions that are executed at
> compile time. If that is the case, what happens if I bind a symbol to a
> macro (not its return value, but the macro itself) and then use that
> symbol to call a macro in a function? Will the macro be called at run
> time as a regular function?

You might want to show some simple code to make your questions easier to
follow. Sounds tho like you mean what happens if you:

(let ((x #'my-macro))
(funcall x))

I am no language lawyer, but I get that same effect simply by compiling
code: (my-macro 1 2 3) before my-macro has been declared, so a run-time
call to my-macro gets compiled in.

At runtime I then get an error, something about trying to call a macro
function.

>
> Also, it looks like a macro can return anything it wants. What happens
> if it returns a function instead of a list?

Well, Lisp is still going to try to compile the value returned as if it
were code, so whatever you return had better be compilable code.

kt

--
Cells? Cello? Cells-Gtk?: http://www.common-lisp.net/project/cells/
Why Lisp? http://lisp.tech.coop/RtL%20Highlight%20Film

"Doctor, I wrestled with reality for forty years, and I am happy to
state that I finally won out over it." -- Elwood P. Dowd

Andreas Thiele

unread,
Feb 1, 2005, 6:49:15 PM2/1/05
to

"CoffeeMug" <coff...@gmail.com> schrieb im Newsbeitrag
news:1107295778.8...@f14g2000cwb.googlegroups.com...

> I'm new to lisp (coming from an extensive C++ background) so I
> apologize in advance if my questions don't make sense.
>
> I realize that lisp macros are regular functions that are executed at
> compile time.

I'm not a guru, but I'm quite sure they are also evaluated during load-time
otherwise you could not use them in interpreted form.

> If that is the case, what happens if I bind a symbol to a
> macro (not its return value, but the macro itself) and then use that
> symbol to call a macro in a function? Will the macro be called at run
> time as a regular function?

A macro cannot be called like a function.
(funcall macro-symbol ...
is not possible

>
> Also, it looks like a macro can return anything it wants.

No - The simple thing about macros is, they just return code. The code
immediately is evaluated during load-time and I think compiled during
compile time. Thus a macro is executed before the compiler 'sees' code. It
will work on the output of the macro.

Of course the code can return a function which then is funcallable like in
the following nonsense code:

(defvar *my-funcs* nil)

(defmacro registering-defun (name (&rest args) &body body)
`(progn
(push (quote ,name) *my-funcs*)
(defun ,name ,args ,@body)))

You can write

(funcall (registering-defun test2 () (princ 1)))

but you cannot execute

(funcall 'registering-defun :whatever-you-type-here-is-not-relevant)

My Lisp says:

Error: Macro or special form REGISTERING-DEFUN called as a function with
args (:WHATEVER-YOU-TYPE-HERE-IS-NOT-RELEVANT).


> What happens
> if it returns a function instead of a list? If I then use the macro in
> some function, what will be the result? If a macro returns a list, it's
> evident, but what about a function object?

The list is immediately evaluted.

>
> Thanks.
>

Andreas


Svein Ove Aas

unread,
Feb 1, 2005, 9:12:38 PM2/1/05
to
Andreas Thiele wrote:
>> If that is the case, what happens if I bind a symbol to a
>> macro (not its return value, but the macro itself) and then use that
>> symbol to call a macro in a function? Will the macro be called at run
>> time as a regular function?
>
> A macro cannot be called like a function.
> (funcall macro-symbol ...
> is not possible
>
Well, you can get at the function with macro-function. Don't do it without
good reason, though.


>>
>> Also, it looks like a macro can return anything it wants.
>
> No - The simple thing about macros is, they just return code. The code
> immediately is evaluated during load-time and I think compiled during
> compile time. Thus a macro is executed before the compiler 'sees' code. It
> will work on the output of the macro.
>

A macro can return anything the compiler will compile; this can include
other things than symbols. Really just as data (to a let), though.
Its return value can be the same as for read, which is why (let ((a #
(make-hash-table))) a) works.


>> What happens
>> if it returns a function instead of a list? If I then use the macro in
>> some function, what will be the result? If a macro returns a list, it's
>> evident, but what about a function object?
>
> The list is immediately evaluted.
>

The function will be inserted in the code wherever the macro form was;
depending on where that is, it may or may not compile, and errors may or
may not happen at runtime.

Doing so is probably not a very good idea, however.

Pascal Bourguignon

unread,
Feb 2, 2005, 5:31:06 AM2/2/05
to
"CoffeeMug" <coff...@gmail.com> writes:

In summary:

- you can call a macro at run-time, only use MACRO-FUNCTION instead
of FUNCTION (that infamous #').

(defun some-condition () (zerop(random 2)))
(defmacro macro-1 (arg) `(print ,arg))
(defmacro macro-2 (arg) `#(not a list ,arg))

(let (a-macro)
(if (some-condition)
(setf a-macro (macro-function 'macro-1))
(setf a-macro (macro-function 'macro-2)))
(funcall a-macro `(,a-macro x) 'x)) ; you must respect
; the macro-function protocol!

Or, you can use macroexpand:

(let (a-macro)
(if (some-condition)
(setf a-macro 'macro-1)
(setf a-macro 'macro-2))
(macroexpand `(,a-macro x)))

In both cases:

--> (PRINT X) ; sometimes
--> #(NOT A LIST X) ; the other times


- you can return anything from a macro. Only, you have to take
care that it will be used as expected. If you return a source
code s-expr, you can use it from another source code s-expr. If
it returns data, you have to call it from data.

(defparameter x `,(macro-2 x))
x --> #(NOT A LIST X)

Of course, you should ask yourself if a function would not have
been better here:

(defun funct-2 (arg) `#(not a list ,arg)) ; three less characters.
(defparameter x (funct-2 'x)) ; one less character.


And if you were asking whether you can get the code generated by the
macro at run-time executed, you can, but you'd have to use EVAL in one
way or the other, taking into account that the lexical environments
are not accesible anymore at run-time (by the compiler). Note that
macros are normally expanded at macro-expansion time that usually
happen long before run-time. If you want to have a run-time generated
macro expanded at run-time you'll have to invoke a macro-expansion
time yourself (calling EVAL, DEFUN, or COMPILE, etc).

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

This is a signature virus. Add me to your signature and help me to live

Rob Warnock

unread,
Feb 2, 2005, 6:56:23 AM2/2/05
to
Andreas Thiele <nos...@nospam.com> wrote:
+---------------

| A macro cannot be called like a function.
| (funcall macro-symbol ...
| is not possible
+---------------

Well, you *can*, but the macro function probably isn't what you'd
think it would be from looking at the DEFMACRO form. For one thing,
it always takes exactly two arguments (&whole form &environment env),
not whatever args the DEFMACRO had:

> (defmacro foo (a b c)
`(list ',a ,b ,(1+ c)))

FOO
> (macro-function 'foo)

#<Interpreted Function "DEFMACRO FOO" {48536BA1}>
> (describe *)

#<Interpreted Function "DEFMACRO FOO" {48536BA1}> is function.
Arguments:
(A B C)
Its defined argument types are:
(T T)
Its result type is:
*
Its definition is:
(LAMBDA (#:WHOLE-984 #:ENV-985) (DECLARE #) (BLOCK FOO #))
> (funcall ** '(foo bar 1 2) nil)

(LIST 'BAR 1 3)
>

[Note that I gave NIL here for the environment, since I don't know
how to hand-craft a CMUCL macro environment.]


-Rob

-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607


Pascal Bourguignon

unread,
Feb 2, 2005, 8:22:22 AM2/2/05
to
Pascal Bourguignon <sp...@mouse-potato.com> writes:
> - you can call a macro at run-time, only use MACRO-FUNCTION instead
> of FUNCTION (that infamous #').
>
> (defun some-condition () (zerop(random 2)))
> (defmacro macro-1 (arg) `(print ,arg))
> (defmacro macro-2 (arg) `#(not a list ,arg))
>
> (let (a-macro)
> (if (some-condition)
> (setf a-macro (macro-function 'macro-1))
> (setf a-macro (macro-function 'macro-2)))
> (funcall a-macro `(,a-macro x) 'x)) ; you must respect
> ; the macro-function protocol!

Oops, reading Rob's answer, you'll have corrected my call:

(funcall a-macro `(,a-macro x) nil#|env|#)) ; I must respect
; the macro-function protocol too!

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

In a World without Walls and Fences,
who needs Windows and Gates?

William Bland

unread,
Feb 1, 2005, 7:06:51 PM2/1/05
to
On Wed, 02 Feb 2005 00:49:15 +0100, Andreas Thiele wrote:

> A macro cannot be called like a function.
> (funcall macro-symbol ...
> is not possible

Several people (including Paul Graham I think?) have recently been
experimenting with first-class macros... I'm not sure if anything good has
come of it.

Cheers,
Bill.

Peter Seibel

unread,
Feb 1, 2005, 6:21:02 PM2/1/05
to
Kenny Tilton <kti...@nyc.rr.com> writes:

> CoffeeMug wrote:
>> I'm new to lisp (coming from an extensive C++ background) so I
>> apologize in advance if my questions don't make sense.
>> I realize that lisp macros are regular functions that are executed
>> at
>> compile time. If that is the case, what happens if I bind a symbol to a
>> macro (not its return value, but the macro itself) and then use that
>> symbol to call a macro in a function? Will the macro be called at run
>> time as a regular function?
>
> You might want to show some simple code to make your questions easier
> to follow. Sounds tho like you mean what happens if you:
>
> (let ((x #'my-macro))
> (funcall x))
>
> I am no language lawyer, but I get that same effect simply by
> compiling code: (my-macro 1 2 3) before my-macro has been declared, so
> a run-time call to my-macro gets compiled in.
>
> At runtime I then get an error, something about trying to call a macro
> function.
>
>> Also, it looks like a macro can return anything it wants. What
>> happens
>> if it returns a function instead of a list?
>
> Well, Lisp is still going to try to compile the value returned as if
> it were code, so whatever you return had better be compilable code.

Also, the code returned can only contain "externalizable" objects. And
functions are not externalizable.

-Peter

--
Peter Seibel pe...@javamonkey.com

Lisp is the red pill. -- John Fraser, comp.lang.lisp

Jens Axel Søgaard

unread,
Feb 3, 2005, 6:43:51 PM2/3/05
to
William Bland wrote:

E.g. Alan Bawden's "First-class Macros Have Types":

<http://www.linearity.org/bawden/mtt/popl00.pdf>

--
Jens Axel Søgaard


drewc

unread,
Feb 3, 2005, 9:27:53 PM2/3/05
to
William Bland wrote:
> Several people (including Paul Graham I think?) have recently been
> experimenting with first-class macros... I'm not sure if anything good has
> come of it.
>

Arc (according to http://www.paulgraham.com/ilc03.html) currently has
first-class macros. We've also yet to see an arc compiler ... the two
could be related ;)

CROMA (Patrick Collison's Esat BT Young Scientist of the Year winning
lisp dialect) has first-class macros as well, but he concludes that they
are a 'bad
idea'(http://lemonodor.com/archives/001038.html).

As Pascal's example shows, in CL "you can call a macro at run-time, only
use MACRO-FUNCTION", but that probably isn't what you want to do. I'm no
macro wizard, but i have trouble seeing any point to 'first-class
macros'.. perhaps i've just yet to come across a situation where they
would be useful.

Maybe in scheme? I've never done anything serious in scheme but the
macro facility seems limited as they appear to be running away from
variable capture (is this one of those save-me-from-myself things?).

drewc

Kalle Olavi Niemitalo

unread,
Feb 5, 2005, 3:26:42 AM2/5/05
to
Peter Seibel <pe...@javamonkey.com> writes:

> Kenny Tilton <kti...@nyc.rr.com> writes:
>
>> Well, Lisp is still going to try to compile the value returned as if
>> it were code, so whatever you return had better be compilable code.
>
> Also, the code returned can only contain "externalizable" objects.

That restriction (in section 3.2.4.1) applies only if the code
will be processed by the file compiler, i.e. COMPILE-FILE, rather
than COMPILE. Moreover, it is possible to compile a file without
processing all the forms in it. Consider:

(eval-when (:compile-toplevel)
(funcall #.#'+ 2 2))

The function + is not an externalizable object, but this does
not matter, because section 3.2.3.1 says the file compiler will
"evaluate" the body of this EVAL-WHEN, rather than "process" it.

0 new messages