【问题标题】:Apply a list of functions to a value将函数列表应用于值
【发布时间】:2014-12-02 23:17:24
【问题描述】:

我正在寻找在 Clojure 中可能非常明确的东西(实际上在整个 Lisp 世界中),但我没有足够的经验或文化来走上正确的轨道,而且 Google 也不是很好到目前为止很有帮助。

假设我有三种简单的形式:

(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))))

虽然这确实有效,但我很惊讶没有更高级别的表单可以做到这一点。我找遍了整个地方,但找不到任何东西。

【问题讨论】:

    标签: clojure functional-programming lisp


    【解决方案1】:

    您要搜索的功能短语是(apply comp operations):

    ((apply comp operations) 42)
    ;48
    

    你的循环确实工作,如果你把它42 喂给value:

    (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 的源代码,您会发现一般情况实质上是在提供函数的reversed 列表上执行类似于您的loop。

    【讨论】:

    • 有趣。我发现了comp,但我的印象是它并没有让我更接近一个可行的解决方案。
    • @Bourdon 如您所见,comp 实现起来并不难,但apply 是基础。
    【解决方案2】:

    “在整个 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
    

    【讨论】:

      猜你喜欢
      • 2015-08-25
      • 2021-07-28
      • 2013-07-25
      • 1970-01-01
      • 2016-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多