在clojure中,如何通过一系列函数?

时间:2013-01-22 21:51:22

标签: clojure

在clojure中,我想通过一系列函数来推送画眉值,但我不确定如何以惯用的方式这样做。我的想法是,我将有一个包含未知数量函数的列表,我想利用鹅口疮的可变性质。

所以,像这样......

(->> 1 inc inc inc)
; 4

(->> 1 '(inc inc inc))
; does not work, of course

4 个答案:

答案 0 :(得分:6)

reduce在这种情况下做得很好

user> (reduce #(%2 %1) 1 [inc inc inc])
4
user> (defn thrush [val funs] (reduce #(%2 %1) val funs))
#'user/thrush
user> (thrush 1 [inc inc inc dec])
3

如果可能的话,坚持使用宏来处理这些事情

答案 1 :(得分:5)

我认为comp是最惯用的选项,不过它会有前缀语法。这也更符合正常的Clojure(fn args)表示法。

=> ((comp inc inc inc) 1)
4

如果函数通常采用可变参数,但是你想要将它作为集合提供,那么将它与惯用语apply结合起来。

=> ((apply comp (repeat 3 inc)) 1)
4

请注意,虽然它从右到左穿线

=> ((comp str inc inc inc) 1)
"4"
=> ((comp inc inc inc str ) 1)
ClassCastException java.lang.String cannot be cast to java.lang.Number

这也更符合Clojure / Lisp s表达式。

如果你想要更“简单”的人类可读符号,Arthur Ulfeldt的回答是完全可以接受的,并且是减少和函数编程的一个很好的例子。 “按原样”使用它可能会妨碍熟悉s表达式的“简单性”..

小心宏!

之所以 - >和 - >>宏是他们主动重写表单,所以你可以在他们的范围内使用通常不完整的参数表示法,如(filter odd?),而不必过度使用partial。这不能通过正常的功能组合来完成。

在转向宏之前,最好学会充分利用normal function composition。对于不习惯的人来说,有很多陷阱,应该谨慎使用。

答案 2 :(得分:2)

怎么样:

user=> (def my-fns [inc inc inc])
#'user/my-fns
user=> (->> 1 ((apply comp my-fns)))
4

答案 3 :(得分:0)

我想你可以这样做:

 (defmacro thrush-list [x flist] `(->> ~x ~@flist))
 (thrush-list 1 [inc inc inc])
 ; 4