guile-devel
[Top][All Lists]
Advanced

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

Re: Syntax checks


From: Dirk Herrmann
Subject: Re: Syntax checks
Date: Sat, 13 Apr 2002 11:01:26 +0200 (MEST)

On Tue, 9 Apr 2002, Lynn Winebarger wrote:

>          The real question (lingering from at least late 2000) seems to be
> whether lambda abstractions should delay expansion as well as evaluation.
> My first impulse is to say it shouldn't, that macros are "evaluated" at read 
> time.  Among other effects of using lambda to delay expansion, you have
> introduced a definite evaluation ordering of applications.  I'm guessing one
> of the appeals of this behaviour is that in
> (define (foo x) (bar x))
> (define (bar x) (+ x 5))
> (define-syntax bar (syntax-rules () ((_ x) (+ x 5))))
> 
>     the 2 definitions of bar work "the same".  However, IMO, the second
> definition should yield an  error in  (foo 4)  because it's evaluation time 
> and bar evaluates to a macro, and 5 is not "syntax". 
>     Mainly, however, I see this as a kind of lexical scoping - if you 
> re-evaluated macros whenever they changed, you have a kind of 
> dynamic scope.  I know this was characterized by Marius in the opposite
> way in the earlier (late 2000) discussion.  I.e. that because macro expanding
> at read time captures whatever value of the syntax binding was lying around
> rather than the binding itself (to be used over and over), it is "dynamic".  
> Well,
> I don't have a great counter to this, it's just my intuition says that 
> expanding
> at read time gives you a "what you get is what you write" promise of 
> lexicality.  Or actually that the other scheme is even more dynamic than 
> expanding at read  time.  Besides which the expansion stage is supposed to 
> occur (completely) before either interpretation or compilation, not 
> intertwined
> with it.  I guess I sort of see define-syntax as implicitly introducing a new,
> inescapable and non-bracketed scope.  
>     Probably the most compelling reason to expand at read time, though is that
> any sane compilation system would not go re-compiling every bit of code just
> because someone redefines lambda or if at the repl.

I agree with you that re-compilation in case of a macro redefinition is of
questionable worth.  Moreover, I don't see a demand for it:  Guile does
not provide such a feature, and I can't remember that I ever saw a user
requesting it on the list.

But, IMO the way guile currently does it is broken (IMO).  Look at the
following example:

(define (foo x) (if x (bar) (bar)))
(defmacro bar () ''first)
(foo #t)
--> first
(defmacro bar () ''second)
(foo #t)
--> first
(foo #f)
--> second
(foo #t)
--> first

First, we see that macro expansion happens during evaluation.  Otherwise,
if expansion was done after 'read, the references to 'bar would not be
expanded: 'bar is not known to be a macro at that time.

Second, we see that there is no re-compilation.  Otherwise the second
execution of (foo #t) would have resulted in 'second.

Third, we see that macro expansion is only done in those paths which are
actually executed.  Otherwise after the first execution of (foo #t) _all_
references to 'bar would have been replaced by 'first.

IMO, the current solution is broken.  Depending on the evaluation order
and the actual execution paths that are taken, you can get completely
different expansions, although the code is syntactically the same.  It is
easy to create an example where it depends on _input data_ how the
expansion will be done.  Ugh.

Thus, I sugggest to first go the way that Lynn suggests: Do expansion
after reading, but don't care about re-compilation.  If we later decide
for re-compilation, we can think about possible solutions then.

Best regards
Dirk Herrmann




reply via email to

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