在clojure中,我想通过一系列函数来推送画眉值,但我不确定如何以惯用的方式这样做。我的想法是,我将有一个包含未知数量函数的列表,我想利用鹅口疮的可变性质。
所以,像这样......
(->> 1 inc inc inc)
; 4
(->> 1 '(inc inc inc))
; does not work, of course
答案 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