匿名函数消耗另一个匿名函数 - clojure koan

时间:2012-05-15 16:45:34

标签: clojure

我正在研究clojure koans,函数中的一个问题需要进一步解释我“得到它”并有一个aha时刻。我能够编写满足问题的函数。但我并不完全理解为什么所有这些都有效。

Clojure> (= 25 ((fn [a b] (b a)) 5 (fn [n] (* n n))))
true

问题1。 我不明白为什么会抛出错误:

Clojure> (= 25 ((fn [b a] (b a)) 5 (fn [n] (* n n))))
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn

所以上面唯一的变化是切换b和a的顺序。 在我的大脑中,我读到了“一个带有a和b的函数”或“b和a”的函数,但是如何使用这些函数取决于后续语句中的parens。为什么订单在这一点上很重要?

问题2。

Clojure> (= 25 ((fn [a] (5 a)) (fn [n] (* n n))))
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn

为什么当我将b的值替换为它所代表的int时,我会收到错误?

Quentions 3。

((fn [a b] (b a)) 5 (fn [n] (* n n))))

为什么这不会引发错误(b a)b在这个例子中是5,这是一个符号。 括号中的第一项预计是函数或特殊形式,除非它是一个列表?

1 个答案:

答案 0 :(得分:6)

  1. 在第一个函数中查看你的表达式:

    (b a)
    

    因为b是第一个,b必须是一个函数。在第二个示例中,您尝试将5传递给b,但5不是函数。使用描述性名称,您可以看到您尝试使用5作为函数:

    ((fn [argument function] (argument function)) ;; problem!!
     5 
     (fn [n] (* n n)))
    

    记住lisps的评估规则:给出这个s-expression:

    (f x y z)
    

    评估f,x,y和z,并将f作为函数应用于x,y和z。

  2. 见答案1 - '5'不是一个功能。使用描述性名称,并轻松发现问题:

    ((fn [function] (5 function)) ;; problem!!
     (fn [n] (* n n)))
    

    更改为:

       ((fn [a] (a 5))  ;; 'a' and '5' flipped
        (fn [n] (* n n)))
    

    让它运行。

  3. 这不是问题:a是5,b(b a)中的函数。使用描述性名称更有意义:

    ((fn [argument function] (function argument)) 
     5
     (fn [n] (* n n)))