我正在研究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,这是一个符号。 括号中的第一项预计是函数或特殊形式,除非它是一个列表?
答案 0 :(得分:6)
在第一个函数中查看你的表达式:
(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。
见答案1 - '5'不是一个功能。使用描述性名称,并轻松发现问题:
((fn [function] (5 function)) ;; problem!!
(fn [n] (* n n)))
更改为:
((fn [a] (a 5)) ;; 'a' and '5' flipped
(fn [n] (* n n)))
让它运行。
这不是问题:a
是5,b
是(b a)
中的函数。使用描述性名称更有意义:
((fn [argument function] (function argument))
5
(fn [n] (* n n)))