Clojure - Currying 技术细节

Clojure - Currying technicalities

我知道 clojure 没有对 currying 的内置支持。但我想了解为什么这段代码失败的技术细节 -->

(defn area-of-triangle
  "Takes the lengths a b and the angle c"
  [a b c]
  (Math/abs (* 0.5 a b (Math/sin c))))


(defn curry
  [a]
  (fn [b]
    (fn [c] ((area-of-triangle a b c))))) 

运行 repl 中的这个 -->

(def a (curry 3))
(def b (a 4))
(def c (b 54.7))

ClassCastException java.lang.Double cannot be cast to clojure.lang.IFn  user$curry$fn__1737$fn__1738.invoke (:4)

有人可以解释一下这里发生了什么吗?为什么c不是三角形面积函数计算出来的值?

非常感谢,亚历克斯

因为这里调用了双函数:

((area-of-triangle a b c))

您正在将函数 area-of-triangle 的结果作为函数调用。

你有一组额外的括号:

(fn [c] ((area-of-triangle a b c)))
        ^

这是一个问题,因为 area-of-triangle 的计算结果是一个数字。假设它被评估为 10,那么你有:

(fn [c] (10))

这没有任何意义,因为 10 不可调用。

这里有两件事:

  1. 您在 (area-of-triangle a b c)
  2. 周围有额外的括号
  3. 柯里化可以使用partial函数

例如:

(defn area-of-triangle
  "Takes the lengths a b and the angle c"
  [a b c]
  (Math/abs (* 0.5 a b (Math/sin c))))


(def a (partial area-of-triangle 3))
(def b (partial a 4))
(def c (b 54.7))  ;; 5.7698490053091875