Clojure で lazy-seq を生む関数についてのトラブルシューティング
Clojure で lazy-seq を生む関数と言うのは cheatsheetの Creating a Lazy Seq に書かれている関数の他に も良く使う所では map 関数なんかもそうだったりする。Programming Clojure を読んだ事があれば 何となく記憶してるかもしれない。
REPL で確かめてみると分かる。
(type (map inc [1 2 3])) ;=> clojure.lang.LazySeq
さて、今回改めて取り上げるのはこの lazy-seq、一部 NPE を誘発する状況があり、 その場合どうするかをメモしておこうと思う。
自分が発生した時の詳細な条件は掴みきれていないものの Java interop, nth 辺りを組み合わせて使っていた時に発生しており、 多分前者じゃないかと予想はしているが未検証。
この話で厄介なのは、REPL や println デバッグだと出ないという事。 REPL も println も lazy-seq を渡しても一度全て評価してから表示するためである。
その場しのぎ的な対応にはなるが、lazy-seq を生む関数なのかどうかは一旦忘れ、 NPE が発生したらシーケンス加工中に lazy-seq になってるのが原因かどうかを確認し そうであれば不格好だが doall とかかましていくように対処する事にした。 lazy-seq を全て避けた標準の代替関数を作るのもかったるいし。
これは機会があればどこで発生するのか改めて検証したい。