[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