📌
Clojure の map で println を出したい時の解決策3選
We love lazy, yes we love! みんな大好き遅延評価 🩷 ですが、ときどき
(map myfunc coll) を実行中 myfunc の中に println を入れて、途中経過を出力させたい ...
というダサい気持ちになりますよね。
たとえば、今どの引数を処理しているのかプリントしたい、とか。
(defn myfunc [x]
(println "Processing:" x)
(* x 2))
こういう時の解決策3選をご紹介します。
doall
で遅延を強制評価
1. doall
を使うと map
の結果を強制的に評価できます。
(doall (map myfunc [1 2 3]))
; Processing: 1
; Processing: 2
; Processing: 3
(2 4 6)
doseq
を使う
2. println
のような副作用を実行したいのであれば、doseq
でも十分です。
doseq
は副作用を実行するためのループなので返り値を持ちません(= nil
を返す)。
(doseq [x [1 2 3]]
(println "Processing:" x)
(* x 2))
; Processing: 1
; Processing: 2
; Processing: 3
nil
(* x 2)
は実行はされますが、どこにも格納されずそのまま破棄されます。
mapv
を使う
3. 個人的に一番かっこいいのはこれです。mapv
は、強制評価してベクタを返します。
(mapv myfunc [1 2 3])
; Processing: 1
; Processing: 2
; Processing: 3
[2 4 6]
mapv
は、内部的に reduce
を使っているので遅延せず評価されます。
以上です! Happy Coding!
2025/03/03 10:55 Updated :
近所から、myfunc
の引数が2つ以上でもできるの?と質問が来ました。mapv
ソースコードを見ると into
使ってあって reduce
じゃないじゃん、と。確かに。
やってみましょう。
(mapv myfunc [1 2 3] [4 5 6])
; Processing: 1 4
; Processing: 2 5
; Processing: 3 6
[4 10 18]
できた。では into
を見に行きます。(reduce
のすぐ上にありました。)
into
の実装にも reduce
が使用されています。なるほど奥深い。
Discussion