<div dir="ltr">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:<div>
<br></div><div>#lang racket<br></div><div><div>(require "x-is-foo.rkt")</div><div>(displayln x)</div><div>(define x 'bar)</div><div>(displayln x)</div></div><div><br></div><div style>Will throw an "identifier is already imported error." Whereas this:</div>
<div style><br></div><div style><div>(parameterize ([current-namespace (make-base-empty-namespace)])</div><div> (namespace-require 'racket)</div><div> (eval '(require "x-is-foo.rkt") (current-namespace))</div>
<div> (eval '(displayln x) (current-namespace))</div><div> (eval '(define x 'bar) (current-namespace)) </div><div> (eval '(displayln x) (current-namespace)))</div><div><br></div><div style>Will happily print</div>
<div style><br></div><div style>foo</div><div style>bar</div><div style><br></div><div style>So I'm still unclear on the difference in underlying principle that yields the different results.</div></div></div><div class="gmail_extra">
<br><br><div class="gmail_quote">On Tue, May 14, 2013 at 9:09 AM, Matthew Butterick <span dir="ltr"><<a href="mailto:mb.list.acct@gmail.com" target="_blank">mb.list.acct@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div>Suppose x-is-foo.rkt is this:</div><div><br></div><div><div>(module x-is-foo racket</div><div> (define x 'foo)</div><div> (provide x))</div><div><br></div><div>If you open another file and try this:</div>
<div><div><br></div><div>(require "x-is-foo.rkt")</div><div>(define x 'bar)</div><div><br></div><div>You'lll get a "identifier already imported" error. OK, that much I understand.</div>
<div><br></div><div>Here's the question. When you do this:</div><div><br></div><div><div>(parameterize ([current-namespace (make-base-empty-namespace)])</div><div> (namespace-require 'racket)</div>
<div> (namespace-require "x-is-foo.rkt")</div><div> (namespace-set-variable-value! 'x 'bar) </div><div> (eval '(print x) (current-namespace)))</div><div><br></div><div>This time, you get 'foo. Why 'foo? Why not another "identifier already imported" error?</div>
<div><br></div><div>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.</div>
<div><br></div><div>It's not a sequencing issue, because if you swap the two lines:</div><div><br></div><div><div>(parameterize ([current-namespace (make-base-empty-namespace)])</div><div> (namespace-require 'racket)</div>
<div> (namespace-set-variable-value! 'x 'bar) </div><div> (namespace-require "x-is-foo.rkt")</div><div> (eval '(print x) (current-namespace)))</div><div><br></div><div>You still get 'foo.</div>
</div><div><br></div><div>Only if you remove the require line:</div><div><br></div><div><div>(parameterize ([current-namespace (make-base-empty-namespace)])</div><div> (namespace-require 'racket)</div>
<div> (namespace-set-variable-value! 'x 'bar) <br></div><div> (eval '(print x) (current-namespace)))</div><div><br></div><div>Do you get 'bar.</div><div><br></div><div><br></div>
</div></div></div></div></div>
</blockquote></div><br></div>