我在Clojure中有以下两个测试用例,一个解构向量,一个解构列表:
int j = 0;
if (rawList.size() > 0)
list.add(rawList.get(0));
for (int i = 1; i < rawList.size(); i++) {
if (rawList.get(i).getMyString()
.equals(list.get(j).getMyString())) {
list.get(j).setMyCount(
list.get(j).getMyCount()
+ rawList.get(i)
.getMyCount());
} else {
j++;
list.add(rawList.get(i));
}
}
为什么符号+在第一个测试用例中评估而不是第二个?引用是递归的,所以在第二个测试用例中user=> ((fn [[a op b]] (op a b)) [1 + 2])
3
user=> ((fn [[a op b]] (op a b)) '(1 + 2))
2
真的是op
吗?
答案 0 :(得分:0)
首先,我们可以通过简单的println简单地查看表单是否按预期方式进行了解构:
(def fn1
(fn [[a op b]]
(println "a>" a)
(println "b>" b)
(println "op>" op)
(op a b)))
(fn1 [1 + 2])
; a> 1
; b> 2
; op> #object[clojure.core$_PLUS_ 0x5b95b23d clojure.core$_PLUS_@5b95b23d]
(fn1 '(1 + 2))
; a> 1
; b> 2
; op> +
所以在第一种情况下,括号会计算clojure.core的函数PLUS,它给出了预期的(+ 1 2)=&gt; 3。
<德尔> 在第二种情况下,您可以将要评估的表单序列描绘为隐式序列,因此对其进行调用eval将给出: (eval('+ 1 2)) ; 2 这只是对序列中每个表单进行评估的结果,因此只返回最后一个值,此处为2。 您可以将其视为: (做 “+ 1 2) 德尔>正如评论中所暗示的那样,不是打电话。
'+是一个实现IFn的clojure.lang.Symbol。因此,当调用eval时,它将使用两个参数1和2调用java函数调用。
(invoke 1 2) ; is called on +'
查看2个参数调用符号的方法:
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Symbol.java#L129
我们注意到它会在第一个参数中搜索符号+',它应该是一个地图。
(def a {'+ 0})
(apply '+ [a 2])
; 0
当找不到项(此处为符号)时,invoke函数返回默认值,即调用函数的第二个参数:
(def b { })
(apply '+ [b 2])
; symbol + is not found in b so returning 2
; 2