解构列表中的函数

时间:2016-12-05 04:22:49

标签: clojure destructuring

我在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吗?

1 个答案:

答案 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