Understanding remove-ns and require

219 views
Skip to first unread message

Mark Melling

unread,
Dec 19, 2017, 5:14:25 PM12/19/17
to Clojure
Hi,

Apologies in advance for the possibly stupid question!

I was having a problem with clojure.tools.namespace.repl/refresh where a namespace that had been successfully loaded subsequently failed to be reloaded when doing a repl/refresh.

Whilst investigating the problem, (this is probably totally unrelated to my issue), I realised I didn't understand how remove-ns and require actually work. 

To illustrate this I did the following:

(require '[foo.bar :as bar])
=> nil
(remove-ns '
foo.bar)
=> #namespace[foo.bar]
(require '[foo.bar :as bar])
=>
CompilerException java.lang.Exception: namespace 'foo.bar' not found, compiling:(*cider-repl foo*:30:7)




So what does remove-ns do to cause the second require to fail? 



Thanks

Mark
 

Andy Fingerhut

unread,
Dec 19, 2017, 7:30:10 PM12/19/17
to clo...@googlegroups.com
I don't have the answer, but perhaps a clue that might lead you to one: the function remove-lib inside of the tools.namespace library does this:

(defn remove-lib
  "Remove lib's namespace and remove lib from the set of loaded libs."
  [lib]
  (remove-ns lib)
  (dosync (alter @#'clojure.core/*loaded-libs* disj lib)))

I suspect that perhaps since in your example REPL session you are not doing anything to change clojure.core/*loaded-libs*, that perhaps it still contains the namespace name on which you called remove-ns.  *loaded-libs* is modified by functions used to implement the behavior of 'require', because require tries to avoid re-loading namespaces that have already been loaded earlier.

Andy

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mark Melling

unread,
Dec 20, 2017, 4:38:06 AM12/20/17
to clo...@googlegroups.com
Thanks Andy, that was helpful.

In my example foo.bar is in *loaded-libs*

I removed it by calling (clojure.tools.namespace.reload/remove-lib 'foo.bar)

Interestingly when I then did a require I get a different error, the file is loaded, but the namespace not found.

(require '[foo.bar :as bar])
=> CompilerException java.lang.Exception: namespace 'foo.bar' not found after loading '/foo/bar', compiling:(*cider-repl foo*:65:7)

Cheers

Mark 




For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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

For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/YEY7lbrNB2w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

Stuart Sierra

unread,
Dec 22, 2017, 12:41:11 PM12/22/17
to Clojure
=> CompilerException java.lang.Exception: namespace 'foo.bar' not found after loading '/foo/bar', compiling:(*cider-repl foo*:65:7)

An error like this usually means that the ns declaration does not match the expected namespace name, based on the file path.

Also be aware that AOT-compilation causes all sorts of havoc with namespace reloading, because AOT-compiled .class files get read by a different ClassLoader. In effect, you cannot "unload" an AOT-compiled namespace. Make sure you do not have any AOT-compiled .class files in your project, and note that some tools and templates enable AOT by default.

–S

Andy Fingerhut

unread,
Dec 22, 2017, 1:27:15 PM12/22/17
to clo...@googlegroups.com
If you do have namespace names that do not correspond with the file name they are placed in, in a Clojure/Java files, Eastwood can find them for you quickly.  Eastwood doesn't analyze ClojureScript files, though.

Andy

https://github.com/jonase/eastwood


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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

For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscribe@googlegroups.com.

Mikhail Gusarov

unread,
Dec 22, 2017, 2:32:40 PM12/22/17
to Stuart Sierra, Clojure


On Fri, 22 Dec 2017, at 18:41, Stuart Sierra wrote:
Also be aware that AOT-compilation causes all sorts of havoc with namespace reloading, because AOT-compiled .class files get read by a different ClassLoader.


Is there any place explaining how exactly Clojure compiles and loads the code? It always feels like magic (especially when it does not work). Names of source code files work too.

Reply all
Reply to author
Forward
0 new messages