Can anyone explain why I can rebind list but not +?
(binding [list vector]
(list 1 3))
(binding [list +]
(list 1 3))
(binding [+ list]
(+ 1 3))
I'd like to rebind + so I can do partial evaluation.
In Clojure 1.1.0 at least, +
with two arguments is inlined for performance. Your binding happens too late. With more arguments it works differently.
Clojure 1.1.0-master-SNAPSHOT
user=> (binding [+ -] (+ 1 2))
3
user=> (binding [+ -] (+ 1 2 3))
-4
One workaround is to make your own namespace and shadow clojure.core/+
with your own function.
user=> (ns foo (:refer-clojure :exclude [+]))
nil
foo=> (defn + [& args] (reduce clojure.core/+ args))
#'foo/+
foo=> (+ 1 2)
3
foo=> (binding [+ -] (+ 1 2))
-1
Note that inlining appears to happen even more aggressively in the current snapshot of Clojure 1.2.0.
Clojure 1.2.0-master-SNAPSHOT
user=> (binding [+ -] (+ 1 2))
3
user=> (binding [+ -] (+ 1 2 3))
6
It may be wisest to use a function name other than +
, e.g. add
, to avoid confusion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With