identityの別名定義でmapを便利にする

Clojureのmapでこういう変換をしたくなるときがよくある。

(1 "piyo" :foo) -> ({:hoge 1} {:hoge "piyo"} {:hoge :foo})

でも、#()で無名関数の定義をしてみると、エラーが出る。
#()の中身は、関数呼び出しorマクロor特殊形式である必要があるため、(#(1))とかやると、「IFnじゃないから呼び出せない」と怒られる。

(map #({:hoge %}) [1 2 3])
-> java.lang.IllegalArgumentException: Wrong number of args passed to: PersistentArrayMap

マップ({})は、元々IFnを継承しているが、引数の数が1個か2個とるので、上記だと「引数の数が違う」と言われてしまう。

下記のようにすれば一応いけるが、もっと簡潔にできそう。

(map (fn [x] {:hoge x}) [1 2 3])
-> ({:hoge 1} {:hoge 2} {:hoge 3})

#()を使うには、引数をそのまま返す関数identityが使える。

(map #(identity {:hoge %}) [1 2 3])
-> ({:hoge 1} {:hoge 2} {:hoge 3})

このままだと、かえって長くなっているので、ideneityの別名を定義する。

(def | identity)

すると、下記のように書ける。

(map #(|{:hoge %}) [1 2 3])
-> ({:hoge 1} {:hoge 2} {:hoge 3})

多少は簡単になったかな?しばらく使ってみよう。

でも、「|」ではない別のもっと良い記号があるかもしれない。