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

Re: Namespaces



> From: Andre van Tonder <andre@xxxxxxxxxxxxxxxxx>
> 
> I have been wondering about the following technical issue:
> 
>    (let ((x 1))
>      (let-syntax ((m (lambda (form)
>                        (let ((x 2))
>                          (syntax x)))))
>        (m))) ?

> Matthias Neubauer <neubauer@xxxxxxxxxxxxxxxxxxxxxxxxxx> writes:
> 
> I don't suggest to return an error but to return "1". As I said
> before, lexical scoping does not apply because (SYNTAX 2) is
> data. You don't expect
> 
> (eval `(let ((x 1))
>           ,(let ((x 2))
>               'x)))
>       
> to evaluate to anything else but 1, right?

First, a closer parallel to the original question is

  (let ((x 1))
     (let ((m (lambda (form)
                 (let ((x 2))
                    (quote x))) ))
        (eval (m '(m)))))

and just to keep all possiblities straight, let's assume we have

  (define x 0)

somewhere before we begin.  So what does this return?

One could imagine it would return 1. and so this is a good
argument.  I must modify my statement that "I don't see how
anyone can advocate otherwise", I now see how one might
be led down this path.

But I am still not buying the conclusion.  As my
philosophy professor used to say: One man's modus ponens
is another's reductio ad absurdum.  I take this as further
proof of the rightiousness of the slogan: Eval is evil.

My example is not valid R5RS Scheme (neither is yours), because
|eval| requires another argument.  If that other argument is
 (scheme-report-environment 5)
then the result is Error: reference to undefined id x.
If the other argument is (interaction-environment) then the
result is 0.  To get a 1 out of this, you need to assume
some kind of (lexical-environment) procedure, which would
give you  an environment where local variables are
visible.

Such a thing is possible, maybe even a good thing for some
purposes, but it still seems like a spanner in the works
for a compilable hygienic macro system.  Back in Elder
Days when |eval| was a great new idea, and symbols were
the same as identifiers, and barely distinguished from
strings, and macros were FEXPR's which were just a recursive
call to |eval| with the program text as argument, I might have
followed you down that path.

But that age of innocence is long gone.  Identifiers are
not symbols, they have a scope manifest in the source
code.  The safe answer to the question is a message from
the compiler asking if you are sure you know what you are
doing, and suggesting that you either rename one of your
local variables to clarify your intention, change
(syntax x) to (quasisyntax ,x), or put in an explicit
call to |eval|.

-- 
     -- Keith Wright

Programmer in Chief, Free Computer Shop
 ---  Food, Shelter, Source code.  ---