It seems ns-unmap only works at the top level (eg. Inside a do but not let). Is this a bug or expected behaviour?
is there a repro for this? I just tried re-creating by calling ns-unmap from a top level form and then from within a let, and both seemed to work
working case (all in a do):
$ bb -e "(do (require '[clojure.set :refer [union]]) (ns-unmap 'user 'union) (def union 10) union)"
10
failing case:
$ bb -e "(do (require '[clojure.set :refer [union]]) (let [] (ns-unmap 'user 'union) (def union 10) union))"
----- Error --------------------------------------------------------------------
Type: clojure.lang.ExceptionInfo
Message: union already refers to #'clojure.set/union in namespace user
Data: {:type :sci/error, :line 1, :column 77, :file "<expr>", :phase "analysis"}
Location: <expr>:1:77
Phase: analysis
----- Context ------------------------------------------------------------------
1: (do (require '[clojure.set :refer [union]]) (let [] (ns-unmap 'user 'union) (def union 10) union))
^--- union already refers to #'clojure.set/union in namespace user
----- Stack trace --------------------------------------------------------------
user/let - <expr>:1:77
user - <expr>:1:45
clojure.core/let - <built-in>
user - <expr>:1:45I don't know off the top of my head, but I do see that if the unmap is done in the let and the let is closed before the def, that seems to work. An initial guess would be that maybe defs are treated in a special-ish way... I'd have to dig a bit deeper (or more likely Michiel comes on in the morning and already knows the exact answer 🙂 )
interestingly, clojure exhibits the same behavior
from a very cursory glance, it looks like both sci (and thus bb) and clojure both intern vars defed in a form (like a let) earlier than executing the functions in that form... I think it has to do with being able to resolve the vars in order to compile the form, but I don't currently know more specifics
The issue is that def is analyzed and causes a side effect during analysis in Clojure. This is the same in SCI.
Analysis/compilation happens on the level of top level forms (except in top level do, those are unnested).
very interesting that clojure does the same thing!