📌
Clojure の map で println を出したい時の解決策3選
We love lazy, yes we love! みんな大好き遅延評価 🩷 ですが、ときどき
(map myfunc coll) を実行中 myfunc の中に println を入れて、途中経過を出力させたい ...
というダサい気持ちになりますよね。
たとえば、今どの引数を処理しているのかプリントしたい、とか。
(defn myfunc [x]
(println "Processing:" x)
(* x 2))
こういう時の解決策3選をご紹介します。
1. doall で遅延を強制評価
doall を使うと map の結果を強制的に評価できます。
(doall (map myfunc [1 2 3]))
; Processing: 1
; Processing: 2
; Processing: 3
(2 4 6)
2. doseq を使う
println のような副作用を実行したいのであれば、doseq でも十分です。
doseqは副作用を実行するためのループなので返り値を持ちません(= nil を返す)。
(doseq [x [1 2 3]]
(println "Processing:" x)
(* x 2))
; Processing: 1
; Processing: 2
; Processing: 3
nil
(* x 2) は実行はされますが、どこにも格納されずそのまま破棄されます。
3. mapv を使う
個人的に一番かっこいいのはこれです。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