On Wed, Jan 19, 2011 at 8:49 AM, Laurent PETIT <laurent.pe...@gmail.com> wrote:
> 2011/1/19 Ken Wesson <kwess...@gmail.com>
>> On Wed, Jan 19, 2011 at 4:06 AM, Laurent PETIT <laurent.pe...@gmail.com>
>> wrote:
>> > 2011/1/18 Ken Wesson <kwess...@gmail.com>
>> >> On Tue, Jan 18, 2011 at 1:07 PM, Stuart Sierra
>> >> <the.stuart.sie...@gmail.com> wrote:
>> >> > You're not really aliasing the Vars, you're creating new Vars and
>> >> > copying
>> >> > the root values from the originals.
>> >> > This leads to subtle bugs when the original Vars are dynamically
>> >> > rebound
>> >> > or
>> >> > redefined.  That's why Compojure dropped `immigrate`.
>> >>
>> >> With 1.3, one could recreate a limited 'immigrate' that only imported
>> >> the non-dynamically-bindable Vars from the target namespace. This
>> >> wouldn't cause subtle bugs, only obvious ones if a wanted Var was
>> >> dynamic and thus didn't get imported.
>> >
>> > No, because in 1.3 it will still (hopefully!) be possible to change the
>> > root
>> > value of vars, be they dynamically rebindable or not.
>>
>> No, because alter-var-root! is an unsafe, mutating operation that
>> should not be done in production code, only at the repl during
>> testing.
>
> Where it would also be painful to have to drop/recreate namespaces using
> this export feature, every time you would alter the root value of the var of
> an exported namespace.

I can count on zero fingers the number of times that I, personally,
have had occasion to use alter-var-root!

> And of course, while we agree that this should not be done in production
> code, there's by definition a difference between theory and practice, and
> "should not be done" does not equate "cannot be done", how opinionated your
> "should" is.

But it does mean that it's less important to avoid possibly creating
additional caveats to using something that is already best-avoided,
such as alter-var-root!.

However, as my earlier post noted a fully general solution would be to
have a means of aliasing Vars, so that multiple symbols in possibly
multiple namespaces referenced the same Var object. In theory it's not
difficult: somewhere for each namespace is a map of symbols to Var
objects, and no inherent reason the same Var couldn't be the value for
multiple keys or a value in multiple such maps.

In fact, only one single new function would need to be in core: one to
intern a symbol in a namespace that takes an existing Var object
rather than creating a new one. (intern 'ns 'name
#'other-ns/other-name) creates a new Var whose root binding is the
existing Var object, but it shouldn't be hard in principle for core to
add an (intern-var 'ns 'name #'existing-var) function that aliases an
existing var in ns under name.

Whether there are other reasons to avoid adding such a feature, I'm
unsure. But it would make the kind of importing discussed in this
thread work without any difficulties with alter-var-root! or with
dynamic Vars.

Now, poking at the clojure.lang.Var methods I don't see any
.getNamespace or similar that would mean that Vars have an enforced
one-to-one relationship with host namespaces, or any .getSymbol or
.getName or similar that would mean that Vars cannot be aliased under
multiple names in a single namespace. So there's no *technical*
obstacle that I can detect to doing this.

The clojure.lang.Namespace class does not, unfortunately, provide any
method to intern a symbol with a preexisting var; it would be simple
enough to wrap such in a Clojure function that interned a preexisting
var into the current namespace with a given symbol name. It has an
intern method that creates a new Var and a refer method that accepts a
symbol and a Var and returns a Var, but the latter does not work if
passed a symbol not currently interned in the namespace and a
preexisting Var. It also has a method to return the namespace's
contents as an IPersistentMap, but this obviously is not usable for
modifying those contents.

So it looks like clojure.lang.Namespace must be modified for such a
feature to be born. It can't be done from inside of Clojure.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to