[gambit-list] Newbie: define-macro question

Kevin Smith kevin at electricanvil.com
Thu Aug 18 13:48:42 EDT 2005


Logan, Patrick D wrote:
>>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
> 
> 

I have On Lisp queued up to read in the very near future. I'm currently 
using Graham's ANSI Common Lisp, the R5RS spec, and Gambit's doc as I 
slowly climb the learning curve.

In your opinion, is it appropriate to use a macro to abstract away 
repetitive boiler-plate code? Or is this better done in a procedure?

--Kevin



More information about the Gambit-list mailing list