[racket] Question about resolution of variable-name conflicts in namespaces

From: Matthew Butterick (mb.list.acct at gmail.com)
Date: Tue May 14 20:01:14 EDT 2013

Some more excavation into the docs revealed that the preferred technique is
to use namespace-require for the initial import only, and then use eval
statements for the rest. That helped me resolve a difficult bug. But it
didn't resolve this variable-override mystery, because this:

#lang racket
(require "x-is-foo.rkt")
(displayln x)
(define x 'bar)
(displayln x)

Will throw an "identifier is already imported error." Whereas this:

(parameterize ([current-namespace (make-base-empty-namespace)])
  (namespace-require 'racket)
  (eval '(require "x-is-foo.rkt") (current-namespace))
  (eval '(displayln x) (current-namespace))
  (eval '(define x 'bar) (current-namespace))
  (eval '(displayln x) (current-namespace)))

Will happily print

foo
bar

So I'm still unclear on the difference in underlying principle that yields
the different results.


On Tue, May 14, 2013 at 9:09 AM, Matthew Butterick
<mb.list.acct at gmail.com>wrote:

> Suppose x-is-foo.rkt is this:
>
> (module x-is-foo racket
>   (define x 'foo)
>   (provide x))
>
> If you open another file and try this:
>
> (require "x-is-foo.rkt")
> (define x 'bar)
>
> You'lll get a "identifier already imported" error. OK, that much I
> understand.
>
> Here's the question. When you do this:
>
> (parameterize ([current-namespace (make-base-empty-namespace)])
>   (namespace-require 'racket)
>   (namespace-require "x-is-foo.rkt")
>   (namespace-set-variable-value! 'x 'bar)
>   (eval '(print x) (current-namespace)))
>
> This time, you get 'foo. Why 'foo? Why not another "identifier already
> imported" error?
>
> I assume I'm missing a subtlety of how the namespace environment is
> different. But according to the docs, both namespace-require and
> namespace-set-variable-value! affect the top-level environment of the
> namespace. So I don't see why the require is silently overriding the
> set-variable-value, rather than causing a conflict.
>
> It's not a sequencing issue, because if you swap the two lines:
>
> (parameterize ([current-namespace (make-base-empty-namespace)])
>   (namespace-require 'racket)
>   (namespace-set-variable-value! 'x 'bar)
>   (namespace-require "x-is-foo.rkt")
>   (eval '(print x) (current-namespace)))
>
> You still get 'foo.
>
> Only if you remove the require line:
>
> (parameterize ([current-namespace (make-base-empty-namespace)])
>   (namespace-require 'racket)
>   (namespace-set-variable-value! 'x 'bar)
>   (eval '(print x) (current-namespace)))
>
> Do you get 'bar.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130514/db4aef0d/attachment-0001.html>

Posted on the users mailing list.