[gambit-list] Newbie: define-macro question
Newcombe, Chris
cnewcom at amazon.com
Thu Aug 18 12:17:06 EDT 2005
Even though it's not a Scheme book, I'd strongly recommend reading this: http://www.paulgraham.com/onlisp.html
It's one of the best books on Common Lisp style macros.
Here's a recent blog entry with some useful material: http://bc.tech.coop/blog/050810.html
This is a fun set of slides too: http://openmap.bbn.com/~kanderso/building/macro/
regards,
Chris
-----Original Message-----
From: gambit-list-bounces at iro.umontreal.ca [mailto:gambit-list-bounces at iro.umontreal.ca] On Behalf Of Logan, Patrick D
Sent: Thursday, August 18, 2005 9:09 AM
To: Kevin Smith; gambit-list at iro.umontreal.ca
Subject: RE: [gambit-list] Newbie: define-macro question
> I'm rather new to Lisp & Scheme (< 3 months total exposure) but I'm
> trying to make a real effort to learn the language. I'm delving into
> macros and having a problem understanding the basics.
>
> I've defined a macro called print-line like so:
>
> (define-macro (print-line msg)
> (list `(display ,msg) `(newline)))
>
> When I try to use the macro from the repl I get the error message:
>
> (print-line "hi")
> hi
> ***ERROR in (console)@38.1 -- Operator is not a PROCEDURE
Adam gave a good explanation of this error and how to solve
it. Another issue for a new Scheme programmer is *when* to use a
macro.
In this example there is one argument and generally you would expect
that argument to be evaluated before printing. Simple procedures serve
this purpose just fine, so the preferred solution would be something
like...
(define (print-line msg)
(display msg)
(newline))
This may be old news to you, and you're just using print-line as an
example. But I have run into so much code over the years where
programmers chose macros where procedures would be simpler.
I choose to implement a macro primarily when I need to control the
order of evaluation, as in a control structure like if, while, etc.
As an example an old Lisp control structure is called PROG1. This
structure takes a sequence of statements, evaluates each in order, and
returns the result of the first statement after the last has been
evaluated. This is can be expressed as a Gambit macro, but I'll call
it begin1 to be more like Scheme's begin than the old Lisp's progn.
> (define-macro (begin1 first-statement . remaining-statements)
(let ((result-var (gensym 'first-result)))
`(let ((,result-var ,first-statement))
, at remaining-statements
,result-var)))
> (begin1 1 2 3)
1
> (begin 1 2 3)
3
> (define result-var 5)
> (begin 1 2 result-var)
5
> (begin result-var 1 2 3)
3
> (begin1 result-var 1 2 3)
5
> (begin1 0 (display result-var) (newline) 1 2 3)
5
0
Then the other nasty thing to watch out for when playing with control
structures is the inadvertent conflict of variables introduced by the
macro and those in the original statements. And so gensym is used to
introduce uniquely named symbols in the macro.
-Patrick
_______________________________________________
Gambit-list mailing list
Gambit-list at iro.umontreal.ca
http://mailman.iro.umontreal.ca/mailman/listinfo/gambit-list
More information about the Gambit-list
mailing list