Suppose I were reading from an InputStream
.
How I would normally do it:
val inputStream = ...
try {
doStuff(inputStream)
} finally {
inputStream.close()
}
Whether or not doStuff
throws an exception, we will close the InputStream
.
How I would do it with iteratees:
val inputStream ...
Enumerator.fromStream(inputStream)(Iteratee.foreach(doStuff))
Will the InputStream
be closed (even if doStuff
throws an exception)?
A little test:
val inputStream = new InputStream() { // returns 10, 9, ... 0, -1
private var i = 10
def read() = {
i = math.max(0, i) - 1
i
}
override def close() = println("closed") // looking for this
}
Enumerator.fromStream(inputStream)(Iteratee.foreach(a => 1 / 0)).onComplete(println)
We only see:
Failure(java.lang.ArithmeticException: / by zero)
The stream was never closed. Replace 1 / 0
with 1 / 1
and you'll see that the stream closes.
Of course, I could maintain a reference to the original stream and close it in case of failure, but AFAIK the idea of using iteratees is creating composable iteration without having to do that.
Is this expected behavior?
Is there a way to use iteratees so the resources are always disposed correctly?