This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Assignment to syntactic keywords in guile


> From: Jim Blandy <jimb@red-bean.com>
> 
> The behavior you've observed is more of a bug than a feature; Guile
> doesn't support it completely:
> 
> guile> (define f (lambda (x) (let* ((x 2) (y (+ x 1))) y)))
> guile> (f 0)
> 3
> guile> (set! let* let)
> guile> (f 0)
> 3
> 
> If the system worked the way you hope, the second application of F
> would return 1, not 3.

I'm not sure what John hopes, but:

guile> (define let* let)      ;;(set! let* let) does same, which is wrong
guile> (define f (lambda (x) (let* ((x 2) (y (+ x 1))) y)))
guile> (f 0)
1

The problem is not that variables and syntactic keywords are
totally disjoint namespaces.  R5RS says (pg 13, 4.3):

  The syntactic keyword of a macro may shadow variable bindings,
  and local variable bindings may shadow keyword bindings.

You could interpret built-in keywords as essentially pre-defined
macros (where, just like the pre-defined functions, the definition
may not be something that could actually be written in Scheme).
The implementation of R5RS macros by Clinger and Rees explictly
works this way, and the example on page 15 of R5RS that uses
LET to re-bind => also requires this interpretation.
See also Notes on pg 45: "There are no reserved identifiers".

All the above results would then be explained because the
macros are expanded away before the program is evaluated
and the SET! is done.  SET! (or any other identifier)
could be a keyword in one scope, and a variable in another,
but you certainly can not use SET! to switch it back and
forth at evaluation time!

Although this interpretation seems to be supported by
the above quote, it runs afoul of the formal syntax in
section 7.1, which makes a distinction between <keyword>
and <synactic keyword>.  If this is accepted, then section
4.3 is in error, because it explicitly uses them
interchangeably.

The general rule is "the English trumps the formal syntax",
but in this case I am not so sure.

> Guile will probably change to become more like R5RS, where syntactic
> keywords and variables are completely distinct.

R5RS is not clear on this point, but in any case
  (set! old-set! set!)
is no good, because SET! does not have a value to assign.

You certainly can say:
  (define-syntax old-set!
    (syntax-rules() ((old-set! V X)
                     (set! V X))))
and
  (let-syntax ((set! (syntax-rules()
                      ((set! V X) #f))))
    set!)
or even
  (let ((set! #f)) set!)
seem OK, but
  (set! set! #f)
is still wrong, because you are assigning to a non-variable,
and
  (define set! #f)
is problematic maybe because you have two definitions of SET!
in the same scope, or maybe because it is equivalent to the
preceding error.  On the other hand, programs are allowed
to redefine built-in procedures (pg 45), so top-level
defines can shadow built-in defines, and maybe this is OK.

-- 
     -- Keith Wright  <kwright@free-comp-shop.com>

Programmer in Chief, Free Computer Shop <http://www.free-comp-shop.com>
         ---  Food, Shelter, Source code.  ---

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]