chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] unbound variable: or


From: Peter Bex
Subject: Re: [Chicken-users] unbound variable: or
Date: Sun, 31 May 2015 13:53:46 +0200
User-agent: Mutt/1.5.21 (2010-09-15)

On Sat, May 30, 2015 at 10:30:38PM -0700, chi wrote:
> On 05/30/2015 07:02 AM, Peter Bex wrote:
> > As has been pointed out time and again, it is fundamentally broken.
> 
> Generally when that is true, you can link to a prepared document explaining it
> clearly and unambiguously.

It's all about hygiene, and gensym doesn't cover the full range of
hygiene issues.  Almost every classic paper about hygienic macros
mentions the hygiene problem at some point:

- Bawden & Rees's "Syntactic Closures" paper starts out with three
   examples of broken macros.
- Hanson's "A Syntactic Closures Macro Facility" also shows an example
   of "a subtle bug" in a macro regarding "if".
- Clinger & Rees's "Macros That Work" contains a description of
   four identifier capturing problems.
- Clinger's "Hygienic Macros Through Explicit Renaming" also shows an
   example where "lambda" must be renamed.
-  In "Implementing Lexically Scoped Macros", Rees shows another example
   of a macro that breaks in two ways.

I didn't bother to check more papers.  The Scheme "community wiki" has
a FAQ page about gensym vs hygiene which is pretty good:
http://community.schemewiki.org/?hygiene-versus-gensym

If you use a search engine you find many more examples.  A quick grab:
http://www.phyast.pitt.edu/~micheles/scheme/scheme28.html
http://eli.thegreenplace.net/2007/09/16/common-lisp-vs-scheme-macros/
http://stackoverflow.com/questions/3893919/mechanics-of-variable-capture-with-define-macro-in-scheme

Even our own wiki has a tutorial which touches on the issue, but it
doesn't really go into detail:
http://wiki.call-cc.org/explicit-renaming-macros

Now, you're probably not going to read all those things I linked,
and they're not all equally clear about the problem, so let's look
at a simple example of a macro containing a bug which cannot be fixed
at all with traditional define-macro:

(define-macro (inc! var)
  `(set! ,var (+ ,var 1)))

Here, set! and + are unhygienically referenced, and may be captured at
the call site.  Using Gambit:

> (define x 1)
> (inc! x)
> x
2
> (let ((+ print)) (inc! x))
21> x
> (print x)
#!void> (set! x 1)
> (let ((set! print)) (inc! x))
12> x
1

Again, note that this bug is unfixable, even with gensym.
If we explicitly rename the identifiers, the problem disappears:

(define-syntax inc!
  (er-macro-transformer
    (lambda (e r c)
      `(,(r 'set!) ,(cadr e) (,(r '+) ,(cadr e) 1)))))

In CHICKEN:

#;2> (define x 1)
#;3> (inc! x)
#;4> x
2
#;5> (let ((+ print)) (inc! x))
#;6> x
3
#;7> (let ((set! print)) (inc! x))
#;8> x 
4

Now, I'll readily agree that this is less readable and somewhat
more error-prone than define-macro because it doesn't check the
argument count.  However, for more complicated macros you need
to do more than just checking the argument count, which defmacro
doesn't help you with either.

In Common Lisp, defmacro is equally broken, but CL has the mitigation of
being a Lisp-2, which means gensym is usually enough to avoid accidental
variable capture: functions live in a different namespace.  This is
expanded upon in the comments section of the Scheme community wiki page
I mentioned earlier.

> ...and I would like to state for the record that even defining hygenic syntax 
> is
> a pretty ruinous idea. You have to be very careful of what you're doing, and
> confident that it's a good idea, because it is literally impossible for 
> someone
> to tell what your program means without first calculating all of the syntax
> rules you have defined in their head. It's so easy to mess with syntax in
> Scheme, and that can be a double edged sword, where the code you produce is
> completely inscrutable because nobody can figure out what the final result of
> syntax producing syntax producing syntax will be.

Macros are not to be used lightly, but in some cases they can be a real
life saver.  That's why Lisp has them and why Scheme has made such a fuss
about trying to have them, but *correctly*.

Cheers,
Peter

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]