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.