Skip to content

Commit

Permalink
last var wins only for clojure.core, #332
Browse files Browse the repository at this point in the history
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
  • Loading branch information
stuarthalloway committed May 22, 2010
1 parent 65ae492 commit 095734a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/clj/clojure/main.clj
Expand Up @@ -194,7 +194,7 @@
(catch Throwable e (catch Throwable e
(caught e) (caught e)
(set! *e e))) (set! *e e)))
(use 'clojure.repl) (use '[clojure.repl :only (source-fn source apropos dir-fn dir)])
(prompt) (prompt)
(flush) (flush)
(loop [] (loop []
Expand Down
14 changes: 8 additions & 6 deletions src/jvm/clojure/lang/Namespace.java
Expand Up @@ -66,12 +66,10 @@ public Var intern(Symbol sym){
if(o instanceof Var && ((Var) o).ns == this) if(o instanceof Var && ((Var) o).ns == this)
return (Var) o; return (Var) o;


// throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name);

if(v == null) if(v == null)
v = new Var(this, sym); v = new Var(this, sym);


warnOnReplace(sym, o, v); warnOrFailOnReplace(sym, o, v);




while(!mappings.compareAndSet(map, map.assoc(sym, v))) while(!mappings.compareAndSet(map, map.assoc(sym, v)))
Expand All @@ -80,7 +78,12 @@ public Var intern(Symbol sym){
return v; return v;
} }


private void warnOnReplace(Symbol sym, Object o, Object v){ private void warnOrFailOnReplace(Symbol sym, Object o, Object v){
if (o instanceof Var) {
if (((Var)o).ns != RT.CLOJURE_NS) {
throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name);
}
}
RT.errPrintWriter().println("WARNING: " + sym + " already refers to: " + o + " in namespace: " + name RT.errPrintWriter().println("WARNING: " + sym + " already refers to: " + o + " in namespace: " + name
+ ", being replaced by: " + v); + ", being replaced by: " + v);
} }
Expand All @@ -101,8 +104,7 @@ Object reference(Symbol sym, Object val){
if(o == val) if(o == val)
return o; return o;


// throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name); warnOrFailOnReplace(sym, o, val);
warnOnReplace(sym, o, val);


while(!mappings.compareAndSet(map, map.assoc(sym, val))) while(!mappings.compareAndSet(map, map.assoc(sym, val)))
map = getMappings(); map = getMappings();
Expand Down
31 changes: 30 additions & 1 deletion test/clojure/test_clojure/rt.clj
Expand Up @@ -30,6 +30,14 @@
~@body ~@body
(str s#)))) (str s#))))


(defn temp-ns
"Create and return a temporary ns, using clojure.core + uses"
[& uses]
(binding [*ns* *ns*]
(in-ns (gensym))
(apply clojure.core/use 'clojure.core uses)
*ns*))

(defmacro eval-in-temp-ns [form] (defmacro eval-in-temp-ns [form]
`(binding [*ns* *ns*] `(binding [*ns* *ns*]
(in-ns (gensym)) (in-ns (gensym))
Expand All @@ -45,7 +53,7 @@
(is (re-matches msg-re (with-err-print-writer (eval-in-temp-ns form)))))) (is (re-matches msg-re (with-err-print-writer (eval-in-temp-ns form))))))


(deftest error-messages (deftest error-messages
(testing "binding a var that already refers to something" (testing "binding a core var that already refers to something"
(should-print-err-message (should-print-err-message
#"WARNING: prefers already refers to: #'clojure.core/prefers in namespace: .*\n" #"WARNING: prefers already refers to: #'clojure.core/prefers in namespace: .*\n"
(defn prefers [] (throw (RuntimeException. "rebound!"))))) (defn prefers [] (throw (RuntimeException. "rebound!")))))
Expand All @@ -72,3 +80,24 @@
(is (contains? (meta #'example-var) :macro)) (is (contains? (meta #'example-var) :macro))
(.bindRoot #'example-var 0) (.bindRoot #'example-var 0)
(is (not (contains? (meta #'example-var) :macro)))) (is (not (contains? (meta #'example-var) :macro))))

(deftest last-var-wins-for-core
(testing "you can replace a core name, with warning"
(let [ns (temp-ns 'clojure.set)
replacement (gensym)]
(with-err-string-writer (intern ns 'prefers replacement))
(is (= replacement @('prefers (ns-publics ns))))))
(testing "you cannot intern over an existing non-core name"
(let [ns (temp-ns 'clojure.set)
replacement (gensym)]
(is (thrown? IllegalStateException
(intern ns 'subset? replacement)))
(is (nil? ('subset? (ns-publics ns))))
(is (= #'clojure.set/subset? ('subset? (ns-refers ns))))))
(testing "you cannot refer over an existing non-core name"
(let [ns (temp-ns 'clojure.set)
replacement (gensym)]
(is (thrown? IllegalStateException
(.refer ns 'subset? #'clojure.set/intersection)))
(is (nil? ('subset? (ns-publics ns))))
(is (= #'clojure.set/subset? ('subset? (ns-refers ns)))))))

0 comments on commit 095734a

Please sign in to comment.