0
(defn sort-map-by-value
  "Given a map return a sorted map, in which the sort is done on the map's values, instead of keys.
   Takes a function as an input, which will be used  for sorting"
  [cf kf]
  (fn [m]
    (->> m
         map-invert
         (into (sorted-map-by #(cf (kf %1) (kf %2))))
         map-invert)))

(defn date-time-comparator
  "Predicate function for comparing two date-time's"
  [time1 time2]
  (before? time1 time2))

(defn get-time-value
  "Function for extracting the date-time from the value of the given map."
  [v]
  (-> v first :time))

(def sort-map-by-date (sort-map-by-value date-time-comparator get-time-value))

(sort-map-by-date {"3-19-2013" [{:time (date-time 2013 3 19 12 14 45)}]
                         "3-9-2013" [{:time (date-time 2013 3 9 16 46 49)}]
                         "2-25-2013" [{:time (date-time 2013 2 25 2 38 15)}]
                         "3-14-2013" [{:time (date-time 2013 3 14 7 19 23)}]
                         "2-8-2013" [{:time (date-time 2013 2 8 12 44 47)}]
                         })

高階関数を使用するための慣用的なパターンを理解しようとしています。特に関数を返す関数の場合。最初の関数sort-map-by-valueは、パラメーターとして2 fnsを取り、パラメーターとしてマップを受け取る関数を返します。

上記の関数は、2つの関数とマップの3つすべてをパラメーターとして受け取ることもできます。したがって、この場合、別の関数を返す関数を作成する必要はありません。それが必要になる場合はどうなるでしょうか。言い換えれば、関数を返す関数を導入するための慣用的なパターンは何ですか?

4

2 に答える 2

1

示されている例は、関数がマップをパラメーターとしても使用する場合に、部分関数アプリケーションを使用して実現できた可能性があります。

基本的に、関数を返す関数は部分適用の特定のケースです。つまり、すべてのパラメーターを関数に渡さず、代わりに残りのパラメーターを取得して元の関数を実行する関数を取得します。私は個人的に、partial無名関数を使用または使用して部分適用を使用して部分関数を作成するのが好きです(例:) #(map inc %)

なぜそれらが必要なのですか?一つには、関数合成を使用してプログラムするときに、それらは接着剤として機能します。例:

ベクトル内の各数値をインクリメントしてから逆にする関数を作成するとします。

関数合成なしで書くことができます:

(defn foo [v]
   (reverse (map inc v)))

関数合成の使用:

(def foo (comp reverse (partial map inc)))

これは最良の例ではないかもしれませんが、あなたがその考えを理解してくれることを願っています。

別の例として、ラッパー関数があります。それらは関数として入力を受け取り、別の関数(元の関数と同じ数のパラメーターを取ります)を返し、元の関数を実行する前または後に何かを実行します(例:リングミドルウェア)

于 2013-03-26T11:25:25.570 に答える
1

についての以前の回答に同意しpartialます。そして、comp複数のfnを入力として受け取り、それらの構成を出力として返すものがあります。

これは役立つかもしれない例ですが、出力は完全にfnではありません。バックグラウンドスレッドで定期的にいくつかのタスクを繰り返し実行したかったのです。各バックグラウンドスレッドは1つの特定のタスクを実行しますが、タスクはスレッドごとに異なります。したがって、繰り返すタスクを表すfnを取り、スレッドを返すHOFを使用することは理にかなっています。ここで、入力fnを継続的に実行するスレッドが作成されます。repeatedly入力fnは、フォーム内にラップされることにより、スレッド内でノンストップで実行されます。

partialこれは、入力と出力の両方がそれぞれ単一のfnであるHOFの最も可能性の高い方法です。私が示した例は、入力fnがその副作用のためだけに必要な場合に何が起こるかです。したがって、HOFに出力がある場合、HOFの出力がfnである意味はありません。

于 2013-04-03T06:07:09.270 に答える