【问题标题】:Reduce a set of functions over a value?在一个值上减少一组函数?
【发布时间】:2010-12-13 23:50:14
【问题描述】:

我正在寻找一种干净、惯用的方式来在 Clojure 中进行“向后减少”。

我有

(def fns '(fn1 fn2 fn3))
(def val 42)

我想获得(fn3 (fn2 (fn1 val))),我对订单并不挑剔。所以我想将一系列函数连续应用于一个值,而不是连续将一系列值应用于一个函数。

建议?谢谢!

【问题讨论】:

    标签: map clojure functional-programming


    【解决方案1】:

    在 Clojure 中写下它的最简单方法是:

    ((comp fn3 fn2 fn1) 42)
    

    【讨论】:

      【解决方案2】:

      另一种思考方式是将其视为函数的组合:

      user=> ((apply comp [inc dec inc]) 42)
      43
      

      【讨论】:

      • 我喜欢这个解决方案,但我认为您将不得不反转函数集合。 ((comp f1 f2 f3) x) 的计算结果为 (f1 (f2 (f3 x))),而提问者则希望反过来。
      • 完全正确。问题确实说明了:“我对订单并不挑剔”,我认为这意味着它们要么是可交换的,要么可以以任何一种方式排列。然而对于某些函数来说,顺序当然是非常重要的 ((apply comp [/ +]) 1 2) -> 1/3 ;;; (((apply comp (reverse [/ +])) 1 2) -> 1/2
      • 我也很喜欢这个解决方案,它最终出现在我的代码中。谢谢!
      【解决方案3】:

      这只是减少。记住函数也是对象。此外,您仍在按 f1、f2 等顺序应用您的功能。 不要与它读取的事实混淆 (f4 (f3 ...

      所以只需使用常规 reduce。

      (reduce #(%2 %1) val functions) 
      

      【讨论】:

      • 非常感谢!顺便说一句,我注意到 (def fns '(fn1 fn2 fn3)) 在这里不起作用,必须使用 (def fns [#'fn1 #'fn2 #'fn3])
      • caffeine.cc:带引号的列表为您提供符号,而不是符号计算的值(函数);这就是引用某事的全部意义所在。你可以做到(list fn1 fn2 fn3) 或[fn1 fn2 fn3];向量版本在 Clojure 中更惯用。
      • +1 我认为这实际上是最好的解决方案,因为它既短又因为 reduce 往往比大多数其他方法具有更好的性能(它在 Clojure 中进行了相当大的优化)
      【解决方案4】:

      怎么样...

      (defn back-reduce
      ([firstfunction restfunctions val]
          (if (= restfunctions nil)
              (firstfunction val)
              (back-reduce (car restfunctions) (cdr restfunctions) (firstfunction val))  
          )
      ))
      

      【讨论】:

      • hmmmm 看起来不像 Clojure 代码,因为它有 "car" 和 "cdr" :-)
      【解决方案5】:

      我也不是一个非常高级的 Clojure 用户,所以 API 描述的语言对我来说往往看起来有点简洁和神秘。但鉴于我的理解有限,“->”宏引起了我的注意。它通过一系列“形式”“串接”一个值 x,这在我看来与您所追求的相似。

      由于它是一个宏,我不确定您是否可以使用(应用)将其推送到您的 fn 列表中,但我会试一试!

      【讨论】:

      猜你喜欢
      • 2019-03-15
      • 1970-01-01
      • 2014-06-15
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 2020-03-29
      • 2020-10-22
      • 1970-01-01
      相关资源
      最近更新 更多