Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add with-redefs
Remove duplication by using with-redefs in binding
  • Loading branch information
trptcolin authored and swannodette committed May 8, 2013
1 parent 29c8597 commit ad771a6
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 17 deletions.
39 changes: 24 additions & 15 deletions src/clj/cljs/core.clj
Expand Up @@ -862,6 +862,28 @@
calls."
`(new cljs.core/Delay (atom {:done false, :value nil}) (fn [] ~@body)))

(defmacro with-redefs
"binding => var-symbol temp-value-expr
Temporarily redefines vars while executing the body. The
temp-value-exprs will be evaluated and each resulting value will
replace in parallel the root value of its var. After the body is
executed, the root values of all the vars will be set back to their
old values. Useful for mocking out functions during testing."
[bindings & body]
(let [names (take-nth 2 bindings)
vals (take-nth 2 (drop 1 bindings))
tempnames (map (comp gensym name) names)
binds (map vector names vals)
resets (reverse (map vector names tempnames))
bind-value (fn [[k v]] (list 'set! k v))]
`(let [~@(interleave tempnames names)]
(try
~@(map bind-value binds)
~@body
(finally
~@(map bind-value resets))))))

(defmacro binding
"binding => var-symbol init-expr
Expand All @@ -871,22 +893,9 @@
are made in parallel (unlike let); all init-exprs are evaluated
before the vars are bound to their new values."
[bindings & body]
(let [names (take-nth 2 bindings)
vals (take-nth 2 (drop 1 bindings))
tempnames (map (comp gensym name) names)
binds (map vector names vals)
resets (reverse (map vector names tempnames))]
(let [names (take-nth 2 bindings)]
(cljs.analyzer/confirm-bindings &env names)
`(let [~@(interleave tempnames names)]
(try
~@(map
(fn [[k v]] (list 'set! k v))
binds)
~@body
(finally
~@(map
(fn [[k v]] (list 'set! k v))
resets))))))
`(with-redefs ~bindings ~@body)))

(defmacro condp
"Takes a binary predicate, an expression, and a set of clauses.
Expand Down
7 changes: 6 additions & 1 deletion test/cljs/cljs/binding_test.cljs
Expand Up @@ -4,4 +4,9 @@
(defn test-binding []
(binding [o/*foo* 2]
(assert (= o/*foo* 2)))
(assert (= o/*foo* 1)))
(assert (= o/*foo* 1)))

(defn test-with-redefs []
(with-redefs [o/bar 2]
(assert (= o/bar 2)))
(assert (= o/bar 10)))
4 changes: 3 additions & 1 deletion test/cljs/cljs/binding_test_other_ns.cljs
@@ -1,3 +1,5 @@
(ns cljs.binding-test-other-ns)

(def ^:dynamic *foo* 1)
(def ^:dynamic *foo* 1)

(def bar 10)
1 change: 1 addition & 0 deletions test/cljs/test_runner.cljs
Expand Up @@ -18,6 +18,7 @@
(string-test/test-string)
(data-test/test-data)
(binding-test/test-binding)
(binding-test/test-with-redefs)
(ns-test/test-ns)
(macro-test/test-macros)
(letfn-test/test-letfn)
Expand Down

0 comments on commit ad771a6

Please sign in to comment.