4

Clojure には、関数の合成にいくつかのオプションがあります。次の合成関数があります。

  • 適用: 「アンラップ」引数用
  • 部分的: まだ与えられていない引数用
  • Comp: 複数の関数を介して連続した結果をパイプするため
  • Juxt: 複数の関数に 1 つの引数を適用するため

ただし、知る限り、分岐を含むそのような合成関数はありません。またはの機能バージョンのように、関数を分岐して構成する関数はありますifcond?

もちろん、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」の場合にデフォルトでIDを返すことが正しい選択であるか、またはそのような場合に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 を調べる必要があります。

モナドを使用すると、関数を連鎖する方法を定義する特定の「バインド」関数を使用して、関数を連鎖させることができます。Maybe モナドや Each モナドのように、何らかの if/else パイプライン処理を行うことも、State モナドのように状態をシミュレートすることもできます。

モナドは Haskell (モナドとして) と F# (「ワークフロー」として) に組み込まれています。私はClojureのモナドライブラリを見てきました(これをチェックしてください)。おそらくArrowライブラリもあります。

于 2012-11-06T22:04:20.260 に答える
1

これは、戦略的プログラミングの考え方に近づいています。あなたは興味のある次の論文を見つけるかもしれません

RalfLämmelとEelcoVisserおよびJoostVisserによる戦略的プログラミングの本質

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 に答える