私はclojureの1.5cond->
マクロに触発されています。
同様に、関数に適用される同じアイデアのマクロを作成したいと思いますmap
。しかし、どこから始めればいいのかわかりません。
たとえば、のソースが見つかりませんcond->
。(おそらくまだリリースされていないためです)
助言がありますか?
私はclojureの1.5cond->
マクロに触発されています。
同様に、関数に適用される同じアイデアのマクロを作成したいと思いますmap
。しかし、どこから始めればいいのかわかりません。
たとえば、のソースが見つかりませんcond->
。(おそらくまだリリースされていないためです)
助言がありますか?
apply-map-> を含むパレットプロジェクトの人々からのさまざまなスレッドマクロがありますが、探しているものとはまったく異なります。
(letfn [(apply-map-
[arg f arg-coll]
`(let [arg# ~arg]
(apply ~f arg#
~@(butlast arg-coll)
(apply concat ~(last arg-coll)))))]
(defmacro apply-map->
"Apply in a threaded expression.
e.g.
(-> :a
(apply-map-> hash-map 1 {:b 2}))
=> {:a 1 :b 2}"
[arg f & arg-coll]
(apply-map- arg f arg-coll))
おそらく、必要なものを選択するのに十分な例がそこにあるでしょう。
map
私が理解していれば、部分的な関数呼び出しのリストを取得し、それぞれに対して(またはapply map
) を最初に追加し、前の結果を最後に追加するマクロを書きたいですか?
これはそのマクロの書き方に直接答えるものではありませんが、いくつかの代替手段があることを指摘したいと思います。
map
これは常に純粋関数に当てはまります。
(=
(map g (map f coll))
(map (comp g f) coll))
リファクタリングされたバージョンは、コレクションを 1 回だけウォークし、中間コレクションを作成する必要はありません。
スレッド化すると、次のようになります。
(=
(->> coll
(map f)
(map g))
(map #(->> % f g) coll))
トランスデューサーは、Clojure でこの種のことを行うためのもう 1 つのパターンですmap
。それらは、レデューサー関数の一種の抽象化です。Clojure のmap
/ filter
/ reduce
(など) は、コレクションなしで呼び出された場合、トランスデューサーを作成します。それらを連鎖させてcomp
、さまざまなコンテキスト (怠惰、熱心、監視可能など) で使用できます。それらに関するRich Hickey のトークは、良いイントロです。