On Tue, Mar 30, 2010 at 10:36 AM, Istvan Devai <ist...@istvandevai.com> wrote:
> Hi,
>
> How can I easily unmap all namespaces in a repl or swank? (so I can continue
> working as if I have just started up the REPL, no matter what I've "use"-d
> previously)
>
> Istvan

I posted a bit of a lengthy exposition on this topic last year after
experimenting with modifying namespaces. Perhaps that will give you
some ideas. See below...

>On Sun, Aug 30, 2009 at 8:46 AM, Adrian Cuthbertson 
><adrian.cuthbert...@gmail.com> wrote:
>> Is there a way to unregister some names from a namespace without reloading 
>> it ?
>
> This is a bit trickier than one might think. An example illustrates this;
>
> Given two files, a.clj...
> (ns a)
> (defn stuff-a [] :stuff-a)
> (defn hello [] :hello)
>
> And b.clj...
> (ns b)
> (defn stuff-b [] :stuff-b)
>
> Say we have an ns 'x which is our running ns which uses 'a and 'b and
> we wish to move the 'hello function into 'b in the files and then
> dynamically reload so that 'x now has the correct mapping to 'hello
> (i.e in 'b)
>
> So in the Repl we'll create an empty ns 'x and change to it...
> user=>(create-ns 'x)
> #<Namespace x>
> user=> (in-ns 'x)
> #<Namespace x>
>
> And load the two files with clojure.core/use ('x does not refer to
> clojure.core so we can see all the ns mapping more clearly)...
> x=> (clojure.core/use 'a)
> nil
> x=> (clojure.core/use 'b)
> ni
>
> So, 'x now sees...
> (clojure.core/ns-refers 'x)
> {hello #'a/hello, stuff-a #'a/stuff-a, stuff-b #'b/stuff-b}
>
> And 'a and 'b contain...
> x=> (clojure.core/ns-publics 'a)
> {hello #'a/hello, stuff-a #'a/stuff-a}
> x=> (clojure.core/ns-publics 'b)
> {stuff-b #'b/stuff-b}
>
> You've probably guessed it by now - to move 'hello from 'a to 'b we have to;
> 1.) Move it from file a.clj to b.clj
> 2.) Re-require and reload 'b
> 3.) Unmap it in the "refers" of 'x
> 4.) Re-refer 'b so 'x  now sees it in 'b
> 5.) Unmap it in the "publics" of 'a
>
> Here's the "dynamic reload" after 1.)...
> 2.) Reload 'b...
> (clojure.core/require 'b :reload)
> nil
> x=> (clojure.core/ns-publics 'b)
> {hello #'b/hello, stuff-b #'b/stuff-b}
> x=> (clojure.core/ns-publics 'a)
> {hello #'a/hello, stuff-a #'a/stuff-a}
> Note that both 'a and 'b now have 'hello loaded but that's ok as 'x
> still only knows about the version in 'a.
>
> 3, 4 and 5.)...
> x=> (clojure.core/ns-unmap 'x 'hello)
> nil
> x=> (clojure.core/refer 'b)
> nil
> x=> (clojure.core/ns-unmap 'a 'hello)
> nil
>
> And so finally we have...
> (clojure.core/ns-publics 'a)
> {stuff-a #'a/stuff-a}
> x=> (clojure.core/ns-publics 'b)
> {hello #'b/hello, stuff-b #'b/stuff-b}
> x=> (clojure.core/ns-publics 'x)
> {}
> x=> (clojure.core/ns-refers 'x)
> {hello #'b/hello, stuff-a #'a/stuff-a, stuff-b #'b/stuff-b}
>
> There still is a problem with this technique - 3.) and 4.) are not
> atomic, so if 'hello is called between those two steps (which is
> likely in a busy web server), that invocation will fail. Note that the
> (ns-remove technique has the same problem, but at a coarser grain
> level).
>
> I think it's worth looking at encapsulating this whole reload
> procedure into a properly atomically protected transaction as it will
> be very useful in many server scenarios. This would probably require
> changes to the namespace functions in core. Any thoughts?

-- 
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

To unsubscribe from this group, send email to 
clojure+unsubscribegooglegroups.com or reply to this email with the words 
"REMOVE ME" as the subject.

Reply via email to