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