将函数列表应用于值

时间:2014-12-02 14:41:39

标签: clojure functional-programming lisp

我正在寻找可能在Clojure中定义得很好的东西(事实上在Lisp世界中)但是我没有足够的经验或文化来走上正确的轨道并且谷歌并不是很好到目前为止很有帮助。

假设我有三种简单形式:

(defn add-one   [v] (+ v 1))
(defn add-two   [v] (+ v 2))
(defn add-three [v] (+ v 3))

出于方便,它们存储在矢量中。在现实世界中,该向量将根据上下文而变化:

(def operations
  [add-one
   add-two
   add-three])

我也有一个初始值:

(def value 42)

现在,我想将该向量中的所有函数应用于该值并获得组合操作的结果:

(loop [ops operations
       val value]
  (if (empty? ops)
    val
    (recur (rest ops)
           ((first ops) val))))

虽然这确实有效,但我很惊讶没有更高级别的形式。我到处都看了,但找不到任何东西。

2 个答案:

答案 0 :(得分:7)

您要搜索的功能词组是(apply comp operations)

((apply comp operations) 42)
;48

如果您为42 value提供<{1}},

(loop [ops operations
       val 42]
  (if (empty? ops)
    val
    (recur (rest ops)
           ((first ops) val))))
;48

这将按照与comp相反的顺序应用操作。

......与使用reduce

一样
(reduce (fn [v f] (f v)) 42 operations)
;48

如果查看comp的源代码,您会发现一般情况基本上在loop列出的reverse d列表中执行与您类似的{{1}}。

答案 1 :(得分:1)

'在Lisp世界中'你可以使用reduce

user> (reduce (fn [x y] (y x)) 5 [inc inc inc inc])
;; => 9

这可能看起来不那么性感,但它适用于各种微小变化(例如,这是Common Lisp):

CL-USER> (reduce (lambda (x y) (funcall y x))
                 '(1+ 1+ 1+ 1+)
                 :initial-value 5)
9