2012/02/18 ClojureのIO処理はJavaのクラスを用いてすることになる.

本体(src/clj/clojure/java/io.clj at 1538d809db22346987075b7f91d37addd33e1afd from clojure/clojure - GitHub) や clojure-contrib の IO処理を見ると

(make-reader (make-input-stream x opts) opts)

という感じのコードがある. なお, make-input-stream 中では例外処理はしていない. Java風の疑似コードで書くと以下の感じになる.

reader = new Reader(new InputStream(x))

このとき, finally 節で reader が null でない場合に close していたとしても,

InputStream インスタンスの生成に成功して Reader

インスタンスの生成に失敗すると, InputStream のインスタンスがリークしてしまう.

ので Java では通常, Reader や Stream のインスタンスは別々の変数に保持して finally

節で 別々に close する. close で 例外が出ることもあるので

IOUtils.closeQueity() を利用することが多い.

clojure の java.io などにはリソースリークしうる問題があるようにみえる.

with-open マクロは, bindings Vector の逆順に close していく. bindings

の数だけ入れ子の try-finally に展開されるので closeQuietly 的な効果があり

正しく使えば問題ない. しかし,

(make-reader (make-input-stream x opts) opts)

的コードでは make-reader でできた reader だけ with-open

してもリークの可能性がある.

私の勘違いでなければ, clojure での IO処理は with-open

を用いて自前でやったほうがよい.