Clojure:如何执行一系列函数?

时间:2016-01-17 22:13:28

标签: function dynamic clojure functional-programming

我有一系列函数(它们会改变某些对象)我想执行它,如果我这样做就可以了:

(foo1)
(foo2)
(foo3)

但是,我想把这段代码放在一个函数中,这样我就可以随时执行这个序列。如果我这样做:

(defn run-foos [] (do (foo1) (foo2) (foo3)))

run-foos创建的突变与之前的3个单独的声明不同。我很抱歉我不能在这里简明地总结我的程序的行为,但基本上我看到上面代码的第一版和第二版之间存在一些行为差异。

我想要做的是有一个函数run-foos,它将执行foo1foo2foo3,其运行方式与我在一行中单独调用每个。我怎么能这样做?

2 个答案:

答案 0 :(得分:3)

在没有看到其余代码的情况下,这里的差异并不明显(一般来说两者是相同的)。

在您拥有的两段代码之间存在任何差异的唯一原因是,如果第一个代码是在repl上输入的,foo1foo2返回了某种懒惰的结果。在这种情况下,repl会在打印时强制执行惰性结果,而run-foos则不会。

如果这是你的问题,那么继续使用run-foos会更好,但重构你的其他功能,以免他们混淆副作用和懒惰。

答案 1 :(得分:0)

此变体仅适用于可变数据。

(defn run-foos [] (do (foo1) (foo2) (foo3)))

但标准的clojure数据结构是不可变的。因此,每当您的数据独立地通过函数时,函数将使用默认数据,其中没有函数的变异。此外,run-foos将仅从最后一次表达返回数据,即(foo3)。

«除了最后一个表达式之外的所有值都会被丢弃,尽管它们会产生副作用。» (Emerick,Carper,Grand:Clojure编程,2012)

我认为你需要线程宏:

(-> data
    foo1
    foo2
    foo3)

它在编译时扩展为(foo3 (foo2 (foo1 data)))。数据将传递给链中的函数,您将获得所需的信息。

在此处阅读有关->宏的示例: https://clojuredocs.org/clojure.core/-%3E