let 绑定中的 Clojure 函数

Posted

技术标签:

【中文标题】let 绑定中的 Clojure 函数【英文标题】:Clojure function in let binding 【发布时间】:2013-05-31 07:08:21 【问题描述】:

如果我有一个计算结果为函数的函数

(defn func1 [c1 c2]
  (fn [x1 x2]
    ...do some stuff with c1 c2 x1))

我在地图的其他地方使用或减少,使用内联会更好

(defn func2 [x y z]
  (reduce (func1 x y) z (range 20)))

或者先绑定它

(defn func2 [x y z]
  (let [ffunc (func1 x y)]
    (reduce ffunc z (range 20))))

在第一种情况下,我担心通过 reduce 的每一步都会生成一个基于 x 和 y 的新函数。

【问题讨论】:

【参考方案1】:

函数调用(func1 x y) 的评估在每种情况下都进行一次。

在 Clojure 中评估函数调用的规则包括评估作为其参数提供的所有表达式,然后使用这些值调用函数。

如果定义以下高阶函数:

(defn plus []
  (println "calling plus")
  +)

然后按如下方式调用reduce:

(reduce (plus) [0 1 2 3])

打印了一个calling plus,表明函数plus只被调用了一次。

使用let 表单时也会发生同样的事情:

(let [f (plus)]
  (reduce f [0 1 2 3]))

希望对你有帮助。

【讨论】:

是的,这正是我想要的。从来没有想过用副作用来测试它。谢谢。 还要注意,实例化函数通常很便宜,所以即使分配了多个函数也没什么大不了的。显然,您可以构建构建起来很昂贵的函数,但这并不像您每次都必须重新编译该函数(我提到这一点是因为闭包的新手通常会在每次构建它们时对其进行编译)。

以上是关于let 绑定中的 Clojure 函数的主要内容,如果未能解决你的问题,请参考以下文章

clojure 函数,左值和返回值

Clojure:虽然 let 绑定不像绑定那样工作?

Clojure let 绑定表单

在没有嵌套 let 的情况下在 Clojure 中绑定多个相关变量

`let` 在 Clojure 中是如何实现的,它的开销是多少?

Clojure:让作用域和函数返回值