Created
September 14, 2017 03:26
-
-
Save laughedelic/815999b02ea0656bd55a8d0cc963a0dd to your computer and use it in GitHub Desktop.
Attach a `finally` block to an iterator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
implicit class IteratorOps[X](val iterator: Iterator[X]) extends AnyVal { | |
/** Attaches a block that will be executed only when the iterator is _completely_ consumed | |
* @note The original iterator should be discarded after calling this method | |
*/ | |
def withFinally(fin: => Unit): Iterator[X] = new Iterator[X] { | |
def next(): X = iterator.next() | |
def hasNext: Boolean = { | |
val has = iterator.hasNext | |
if (!has) fin | |
has | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is very handy when you want to transform (map) an iterator with some side-effects on the way and get the used resources closed in the end. For example, you can define such method:
Note, that you can't just close stream, because it will happen before any iterator element is evaluated.
Here nothing happened yet, you just defined a new iterator.
And only after you consume it completely:
lines.foreach(println)
, thengz
andreader
will get closed.