William James
4/2/2015 6:53:00 PM
Peter Seibel wrote:
> > I know it's a poor example, but anyways. The point is that the compiler
> > cannot know at preprocessor time the value of X and thus how many 7s
> > put in the list instruction. Can someone explain what happens here?
>
> Sure it can, you passed it the literal object 3:
>
> (defmacro give-me-a-list-of-X-sevens (num)
> `(list ,@(loop repeat num collect 7)))
>
> That is, at macro-expansion time (a better term than "compiler
> pre-processor time", btw), the parameter NUM is bound to the object 3.
> However, if the macro is written that way, you can't do is this:
>
> (let ((x 3))
> (give-me-a-list-of-X-sevens x))
>
> because the macro GIVE-ME-A-LIST-OF-X-SEVENS will get the object X
> (i.e. the symbol named "X") and will try and use it as an argument to
> the REPEAT clause of the LOOP which will barf. If you understand the
> difference between these two cases you will be well on your way to
> grokking macros.
>
> -Peter
>
> P.S. if you wanted both uses of the macro to "work" you might write it
> like this:
>
> (defmacro give-me-a-list-of-x-sevens (num)
> (typecase num
> (number `(list ,@(loop repeat num collect 7)))
> (t `(loop repeat ,num collect 7))))
>
> in this version we generate (slightly) more efficient code in the case
> where the value of num is known at macro-expansion time, and otherwise
> generate code that does all the work at runtime.
Gauche Scheme:
(define-macro (list-of-x-sevens num)
(if (number? num)
`(list ,@(make-list num 7))
`(make-list ,num 7)))