guile-devel
[Top][All Lists]
Advanced

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

Trouble with `export'.


From: Marius Vollmer
Subject: Trouble with `export'.
Date: 04 Jun 2001 01:02:08 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.0.102

Hi,

I'm having trouble with `export'.  With my recent change

        * boot-9.scm (module-ensure-variable!): New.
        (module-export!): Use it to ensure that there is a variable to
        export.  Previously, we would always create a new variable, copy
        the value over, and export the new variable.  This confused
        syncase since it keys important properties on variables.

the semantics of export have subtly changed and will cause problems.

Prior to that change, re-exporting imported bindings would not work
exactly right.  This code

    (define-module (mod1))
    (export name1)          ;; Create uninitialized var1 and put it 
                            ;; into mod1 and the interface of mod1
    (define name1 12)       ;; Store 12 in var1


    (define-module (mod2))
    (use-modules (mod1))    ;; Make var1 visible with the name name1
    (export name1)          ;; create var2 and initialize it with the
                            ;; value of var1.  Put var2 into mod2 and
                            ;; its interface.

    (define-module (mod3))
    (use-modules (mod2))    ;; Make var2 visible with the name name1
    (set! name1 123)        ;; Store 123 into var2.  Wrong.

would create two variables.  This is not the right thing, since we
want modifications to be consistent.

After the change, this would work right.  However, this code

    (define-module (mod1))
    (export name1)          ;; Create uninitialized var1 and put it 
                            ;; into mod1 and the interface of mod1
    (define name1 12)       ;; Store 12 in var1


    (define-module (mod2))
    (use-modules (mod1))    ;; Make var1 visible with the name name1
    (export name1)          ;; Put var1 into the public interface of mod2
    (define name1 123)      ;; Create var2 with name name1 and store 12 in it.


    (define-module (mod3))
    (use-modules (mod2))    ;; Make var1 visible with the name name1
    (display name1)         ;; Display 12.  Wrong.

will put the wrong variable into the public interface of mod2.  This
happens since `export' can not know whether there will be a local
definition for a name later on.

The latter problem can be fixed by putting the export after the
definition:

    (define-module (mod2))
    (use-modules (mod1))    ;; Make var1 visible with the name name1
    (define name1 123)      ;; Create var2 with name name1 and store 12 in it.
    (export name1)          ;; Put var2 into the public interface of mod2

Now `export' sees the local variable var2 and uses it.

This is not a good fix since it is not common practice to write code
in that way, and it fails silently when not doing it right.  What's
worse, whether it fails or not depends on what bindings are visible
from imported modules, which is not a locally visible thing, usually.


A right fix, I think, would be when `export' keeps a list of exported
names, and the corresponding variables are found lazily when a
exported name is actually referred to.

Another possibility is to distinguish between exporting locally
defined names, and re-exporting imported names.  `export' would work
like it did before my change (except it wouldn't copy values from
imported bindings), and the new `reexport' would only export existing
bindings that come from used modules.


I'm not sure what to do.  The behavior now is worse than it was
before, but neither is right.  I have reverted my change, which makes
syncase fail again, but hopefully will save a lot of people from
subtle bugs.  I already had my share.  (And deservedly so :-)

What do you think.



reply via email to

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