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

macro help

73 views
Skip to first unread message

Tom Kwong

unread,
May 10, 2013, 2:20:58 AM5/10/13
to
Hi. Can anyone help me understand why num isn't recognized? thanks

(define-syntax macro-test
(syntax-rules ()
((_ body ...)
(let ((num 2))
body ...))))

(macro-test (print 1) (print (* num num)))

=> Error: unbound variable: num

Call history:

<eval> (##sys#eq? l7052 (quote ()))
<eval> (##sys#cons (rename7060 (##core#syntax let)) (##sys#cons (##sys#cons (##sys#cons (rename7060 (##core......
<eval> (rename7060 (##core#syntax let))
<eval> (##sys#cons (##sys#cons (##sys#cons (rename7060 (##core#syntax num)) (##sys#cons (quote7059 2) (quot......
<eval> (##sys#cons (##sys#cons (rename7060 (##core#syntax num)) (##sys#cons (quote7059 2) (quote7059 ()))) ...
<eval> (##sys#cons (rename7060 (##core#syntax num)) (##sys#cons (quote7059 2) (quote7059 ())))
<eval> (rename7060 (##core#syntax num))
<eval> (##sys#cons (quote7059 2) (quote7059 ()))
<syntax> (##core#let ((num7082 2)) (print 1) (print (* num num)))
<syntax> (##core#begin (print 1) (print (* num num)))
<syntax> (print 1)
<syntax> (print (* num num))
<syntax> (* num num)
<eval> (print 1)
<eval> (print (* num num))
<eval> (* num num) <--

John Cowan

unread,
May 10, 2013, 12:00:15 PM5/10/13
to
On Friday, May 10, 2013 2:20:58 AM UTC-4, Tom Kwong wrote:

> Hi. Can anyone help me understand why num isn't recognized? thanks
>
> (define-syntax macro-test
> (syntax-rules ()
> ((_ body ...)
> (let ((num 2))

This binds num textually within the macro, which does not in fact contain any references to "num", so the binding is useless.

> body ...))))
>
> (macro-test (print 1) (print (* num num)))

It does not mean that num is bound in the body with which the macro is invoked. That can only be done by a let (or equivalent) that surrounds the macro call. Since there is no such binding, you get:

> => Error: unbound variable: num

--
Knowledge studies others / Wisdom is self-known; John Cowan
Muscle masters brothers / Self-mastery is bone; co...@ccil.org
Content need never borrow / Ambition wanders blind; http://ccil.org/~cowan
Vitality cleaves to the marrow / Leaving death behind. --Tao 33 (Bynner)

Nils M Holm

unread,
May 10, 2013, 12:36:20 PM5/10/13
to
John Cowan <johnw...@gmail.com> wrote:
> On Friday, May 10, 2013 2:20:58 AM UTC-4, Tom Kwong wrote:
> > (define-syntax macro-test
> > (syntax-rules ()
> > ((_ body ...)
> > (let ((num 2))
>
> This binds num textually within the macro, which does not in fact
> contain any references to "num", so the binding is useless.
>
> > body ...))))
> >
> > (macro-test (print 1) (print (* num num)))
>
> It does not mean that num is bound in the body with which the
> macro is invoked. That can only be done by a let (or equivalent)
> that surrounds the macro call.

In other words: there is no definition of NUM in the context
in which the macro is expanded, so NUM is undefined. The NUM
inside of the macro is local to the macro and cannot be accessed
from the outside.

It may also be educational to know that

(macro-test (print 1) (print (* num num)))

certainly will *not* expand to

(let ((num 2))
(print 1)
(print (* num num)))

but rather to something like

(let ((##12867871 2))
(print 1)
(print (* num num)))

due to hygiene. This also illustrates nicely why NUM is undefined.

The effect you are trying to achieve here (name capturing) cannot be
implemented with DEFINE-SYNTAX. You will need something more low-level,
like DEFINE-MACRO (which is, of couse, frowned upon in Scheme-land).

--
Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org

Marco Maggi

unread,
May 10, 2013, 5:14:01 AM5/10/13
to
Tom Kwong wrote:
> Can anyone help me understand why num isn't recognized?
> thanks

> (define-syntax macro-test
> (syntax-rules ()
> ((_ body ...)
> (let ((num 2))
> body ...))))

> (macro-test (print 1) (print (* num num)))

> => Error: unbound variable: num

Because you are using a Scheme implementation providing
hygienic macros. In the template of the SYNTAX-RULES:

(let ((num 2))
body ...)

the identifier NUM appears in "binding position", that is:
as left-hand side of a binding definition:

-- left-hand side
|
v
(let ((symbol value)) body)

so the hygienic macro expander substitutes all the instances
of NUM inside the LET macro with a uniquely generated
symbol.

After the expansion of:

(macro-test (print 1) (print (* num num)))

the code being evaluated is similar to:

(let ((G0 2))
(print 1)
(print (* num num)))

and NUM is unbound.
--
Marco Maggi

Tom Kwong

unread,
May 11, 2013, 3:32:01 AM5/11/13
to
Thanks. It makes perfect sense though it also makes my life tougher :-)

Tom Kwong
http://ahsmart.com

Barry Margolin

unread,
May 11, 2013, 1:09:52 PM5/11/13
to
In article <c770df6b-beb7-4bce...@googlegroups.com>,
Tom Kwong <tk3...@gmail.com> wrote:

> Thanks. It makes perfect sense though it also makes my life tougher :-)

The problem is that what you're trying to do with your macro goes
against general Scheme philosophy.

(define (some-fun num)
(macro-test
(write num)))

Your macro, if it worked, would shadow the argument "num", but there's
nothing visible that shows that this is happening. Your macro also
can't be nested easily.

The general approach that macros are supposed to take is that if they
introduce new variable bindings, the variable should be named in the
invocation. That way the lexical scoping matches the visible notation.

It's occasionally necessary to violate this, and this is why the
lower-level macro facilities provide ways to do it. But the high-level
interface implements the common, hygienic method.

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

lewis...@sdf.lonestar.org

unread,
May 15, 2013, 3:34:26 PM5/15/13
to
You can do exactly what you want using a traditional macro:

(define-macro macro-trad
(lambda args `(let ((num 2)) ,@args)))

(macro-trad (print 1) (print (* num num)))

1
4

Stephen Lewis
0 new messages