4

在 Clojure 中,有多种组合函数的选项。有组合功能:

  • 应用:用于“展开”参数
  • 部分:对于尚未给出的论点
  • Comp:用于通过多个函数传递连续结果
  • Juxt:用于在多个函数上应用一个参数

但是,AFAIK 没有包含分支的此类组合功能。是否有任何以分支方式组成函数的函数,例如ifor的函数版本cond

当然,一个 if 版本很容易制作(尽管这个实现可能不是最快的):

(defn iff
  ([pred rtrue] (iff pred rtrue identity))
  ([pred rtrue rfalse]
    (fn [& args]
      (if (apply pred args)
        (apply rtrue args)
        (apply rfalse args)))))

可能会讨论默认情况下在“else”情况下返回身份是正确的选择,或者在这种情况下是否应该返回 nil。

使用此类功能可以生成更易于阅读的代码。取而代之的是#(if (string? %) (trim %) %)(iff string? trim)或带有 cond 版本:

(condf string? trim,
       vector? (partial apply str),
       :else identity)

其他 FP 语言有这样的结构吗?我可以想象它在与 comp 和 juxt 的组合中可能会很方便。为什么没有 Clojure ?

好的 iff / condf 实现的奖励积分:)

4

3 回答 3

2

我不确定这是否与您正在寻找的内容直接匹配(对我来说,这个问题有点模糊),但您应该研究一下 Monads 和 Arrows。

Monad 允许您将函数与定义如何链接它们的特定“绑定”函数链接在一起。它可以进行某种 if/else 流水线操作,例如在 Maybe 和 Either monad 中,或者它可以模拟状态,例如在 State monad 中。

单子内置于 Haskell(作为单子)和 F#(作为“工作流”)中。我已经看过 Clojure 的 monad 库(检查一下),并且可能也有 Arrow 库。

于 2012-11-06T22:04:20.260 回答
1

这接近了战略规划的想法。您可能会发现以下感兴趣的论文

Ralf Lämmel 和 Eelco Visser 以及 Joost Visser的战略规划的本质

http://homepages.cwi.nl/~ralf/eosp/

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.20.1969

于 2012-11-07T01:48:08.647 回答
1

好吧,您可能会想出许多这样的组合模式并问为什么这不在核心语言中。原因很明显,不可行。该语言的核心为您提供了构建此类模式的所有结构。这些特性更像是contrib一种东西,而不是语言的核心。

就实现而言,它就像下面所示的那样简单:

(defn condf [& args]
  (let [chain (partition 2 args)]
    (fn [& params]
      (first (for [[p f] chain :when (or (= :else p) (apply p params))]
                (apply f params))))))

(def my-func (condf string? clojure.string/trim 
                  vector? (partial apply str)
                  :else identity))

(my-func "Ankur ") ==> "Ankur"
(my-func [1 2 3]) ==> "123"
(my-func '(1 2 3)) ==> (1 2 3)
于 2012-11-07T04:30:40.557 回答