Clojure - Currying的技术细节

时间:2018-03-26 14:05:21

标签: clojure currying

我知道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不能成为三角形面积函数计算的值?

非常感谢,Alex

3 个答案:

答案 0 :(得分:1)

这是因为这里有双重函数调用:

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

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

答案 1 :(得分:1)

你有一组额外的括号:

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

这是一个问题,因为area-of-triangle评估为一个数字。说它评估为10,然后你有:

(fn [c] (10))

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

答案 2 :(得分:1)

这里有两件事:

  1. (三角区域a b c)附近有额外的括号
  2. 对于currying,您可以使用 partial 功能
  3. e.g:

    (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