TL;DR
- Clojure のスレッディングは、並行処理のスレッドとは関係なく、コードを直感的に書く方法である。
->は値を次のフォームの第 1 引数に、->>は最終引数に、as->は任意の位置に渡す。cond->とcond->>は条件ごとにスレッディングする。
内容
他の言語でも使われるスレッド(threads)と、Clojure で使われるスレッディング(threading)は全く関係ないので注意する。スレッディングはコードの塊を並行して実行することを指すのではなく、Clojure でコードを直感的に書く方法を指す。
-> マクロ
最初に指定された値(5)を、次のフォーム((Math/pow …))の第 1 引数として渡す。これを最後のフォームまで繰り返す。
(-> 5
(Math/pow 2)) ; 25そのため、上の式は次と同じ意味になる。
(Math/pow 5 2) ; 25-> マクロは一連のフォームの処理をまとめるときに真価を発揮する。
(-> 10
inc
(* 2)
(+ 5))上の式は次と同じ意味になる。
(+ (* (inc 10) 2) 5)比べると、-> マクロを使ったほうが読みやすい。
->> マクロ
-> と似ているが、値が入る位置が最終引数の位置になる点が違う。
(->> 5
(Math/pow 2)) ; 32そのため、上の式は次と同じ意味になる。
(Math/pow 2 5) ; 32こちらも、一連のフォームの処理をまとめるときに真価を発揮する。
(->> 5
(Math/pow 2)
inc) ; 33上の式は次と同じ意味になる。
(inc (Math/pow 2 5))as-> マクロ
-> や ->> と違い、関数の任意の位置に値を渡せる。
(as-> 5 x
(Math/pow x 2)) ; 25このコードでは変数 x に 5 を束縛し、Math/pow の第 1 引数として使っている。同じように、Math/pow の第 2 引数にするときは次のように書ける。
(as-> 5 x
(Math/pow 2 x)) ; 32cond->, cond->> マクロ
条件ごとにスレッディングしたいときは、cond-> と cond->> マクロを使える。cond-> と cond->> の違いは、-> と ->> の違いと同じく、値が次のフォームの第 1 引数に渡されるか最終引数に渡されるかだけである。
まず、cond-> の例を見る。
(let [a 11]
(cond-> []
(odd? a) (conj (* a 2))
(even? a) (conj (/ a 2)))) ; 22このコードでは、初期値として空配列([])を渡し、a が奇数か偶数かで処理を分けている。
- 奇数のとき、
aを 2 倍した値を空配列に追加する(実際に処理されるコード:(conj [] (* a 2))) - 偶数のとき、
aを 1/2 にした値を空配列に追加する(実際に処理されるコード:(conj [] (/ a 2)))
今回は a が 11 なので、(conj [] (* 11 2)) が実行され、[22] を得る。
同じように、cond->> の例を見る。
(let [a 10]
(cond->> 1
(odd? a) (* a 2)
(even? a) (/ a 2))) ; 5このコードでは、初期値として 1 を渡し、a が奇数か偶数かで処理を分けている。
- 奇数のとき、
(* a 2 1)を実行する - 偶数のとき、
(/ a 2 1)を実行する
今回は a が 10 なので、(/ 10 2 1) が実行され、5 を得る。
キーワード
自分の理解
次の資料を参考にした。