guile-devel
[Top][All Lists]
Advanced

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

define and modules


From: Dirk Herrmann
Subject: define and modules
Date: Sun, 20 Oct 2002 18:17:04 +0200 (CEST)

On 19 Oct 2002, Marius Vollmer wrote:

> Dirk Herrmann <address@hidden> writes:
> 
> > Summarized:
> > * The compiler must be able to emit code that allows references to
> >   identifiers to be looked up at use time (that is, in the executor).
> > * The executor must be able to handle definitions.
> > * Once a binding has been referenced, the binding should not change.
> 
> Yes, that's exactly the way I see it as well.  The constraints that
> new-model.txt puts on the module system work in this direction.

Great.  However, currently, guile's handling of defines is buggy or at
least in contrast to R5RS.  Changing it would break existing code as shown
in the following two examples:

Example 1:
==========
(define x (begin (set! x #f) #t))
 --> ERROR: Unbound variable: x

If I understand R5RS correctly, (define x y) should first bind the
identifier x to a location and _then_ execute the assignment (set! x y).
That means, guile's behaviour is wrong here.  The reason is, that guile
first executes y and _afterwards_ binds and assigns x.  This bug could be
fixed by changing the order in which guile deals with defines.  However,
then we would have a problem with the following code:


Example 2:
==========
(define-module (guile))
(define foo #t)
(define-module (bar))
foo
 --> #t
(define foo (not foo))
foo
 --> #f
(define-module (guile))
foo    
 --> #t

According to R5RS, a 'define expression on the top-level has exactly the
same effect as an assignment expression if the identifier is bound.
Guile, however, behaves differently here:  An expression (define x y)
executes y making use of bindings that potentially come from other
modules.  Then, if x is bound _within_the_current_module_ an assignment is
performed.  Otherwise, if x is not bound or bound in another module, a new
binding is created in the current module.


Example 1 and 2 show two aspects where the current handling of guile's
define is wrong (with respect to R5RS):  First, if a binding exists, guile
does not simply perform an assignment, and second, if no binding exists,
guile does not as a first step create one.

Unfortunately, there is code that depends on this behaviour:

(define-module (srfi srfi-17) ...)
...
(define setter
  (getter-with-setter
   setter
   (lambda args
     (error "Setting setters is not supported for a good reason."))))


In fact, the way guile currently handles 'define expressions, bindings get
re-defined after they have been referenced!  Look at the following
expression:

(define-module (guile))
(define foo #t)
(define-module (bar))
(define (old) foo)       ;  references the old binding in module (guile)
(old)
 --> #t
(define foo #f)          ;  new binding for foo in module (bar)
(define (new) foo)       ;  references the new binding in module (bar)
;; and now:
;; new and old reference different bindings for foo:
(new)
 --> #f
(old)
 --> #t

Best regards, 
Dirk Herrmann





reply via email to

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