任何人都可以解释为什么我可以重新绑定列表,但不是+?为什么我不能在clojure中绑定+?
(binding [list vector]
(list 1 3))
(binding [list +]
(list 1 3))
(binding [+ list]
(+ 1 3))
我想重新绑定+所以我可以做部分评估。
任何人都可以解释为什么我可以重新绑定列表,但不是+?为什么我不能在clojure中绑定+?
(binding [list vector]
(list 1 3))
(binding [list +]
(list 1 3))
(binding [+ list]
(+ 1 3))
我想重新绑定+所以我可以做部分评估。
在Clojure 1.1.0中,至少有+
带有两个参数的内联以获得性能。你的约束发生得太晚了。随着更多的参数,它的工作方式不同
Clojure 1.1.0-master-SNAPSHOT
user=> (binding [+ -] (+ 1 2))
3
user=> (binding [+ -] (+ 1 2 3))
-4
一个解决办法是让自己的命名空间,并用自己的功能影子clojure.core/+
。
user=> (ns foo (:refer-clojure :exclude [+]))
nil
foo=> (defn + [& args] (reduce clojure.core/+ args))
#'foo/+
foo=> (+ 1 2)
3
foo=> (binding [+ -] (+ 1 2))
-1
请注意,在Clojure 1.2.0的当前快照中内联似乎更加积极地发生。
Clojure 1.2.0-master-SNAPSHOT
user=> (binding [+ -] (+ 1 2))
3
user=> (binding [+ -] (+ 1 2 3))
6
这可能是明智的使用比+
,例如其他的功能名add
,以避免混淆。
快速解决方法:使用让而不是结合,这会为你工作得很好:
user=> (let [+ list] (+ 2 3))
(2 3)
一点(不完全)挖掘到的原因:
取看看+功能的来源:
(defn +
"Returns the sum of nums. (+) returns 0."
{:inline (fn [x y] `(. clojure.lang.Numbers (add ~x ~y)))
:inline-arities #{2}}
([] 0)
([x] (cast Number x))
([x y] (. clojure.lang.Numbers (add x y)))
([x y & more]
(reduce + (+ x y) more)))
请注意,有多个内联函数定义了不同数量的参数。如果试图重新绑定0或1元数的定义,它工作得很好:
user=> (binding [+ (fn [] "foo")] (+))
"foo"
user=> (binding [+ (fn [a] (list a))] (+ 1))
(1)
现在,这绝对不为2个参数的情况下工作(如你发现)。我并没有把点连接起来,但是。 (特殊形式)使我怀疑结合是一个宏,而让我们是一个特殊的形式...
特别是调用arity 2元数据似乎也可疑。
他们肯定会对Clojure 1.2.0的最终版本采取这种积极的内涵,因为最后一个表达式给了我-4。 –