Merge remote branch 'origin/master'

This commit is contained in:
Alex Tkachman
2012-01-04 14:29:34 +02:00
2 changed files with 45 additions and 12 deletions
+12 -2
View File
@@ -67,7 +67,7 @@ private val stdin : BufferedReader = BufferedReader(InputStreamReader(object : I
inline fun readLine() : String? = stdin.readLine() inline fun readLine() : String? = stdin.readLine()
/** Uses the given resource then closes it to ensure its closed again */ /** Uses the given resource then closes it to ensure its closed again */
inline fun <T: Closeable, R> T.use(block: (T)-> R) : R { inline fun <T: Closeable, R> T.foreach(block: (T)-> R) : R {
var closed = false var closed = false
try { try {
return block(this) return block(this)
@@ -118,7 +118,17 @@ inline fun Reader.buffered(): BufferedReader = if(this is BufferedReader) this e
inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize) inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize)
inline fun <T> Reader.useLines(block: (Iterator<String>) -> T): T = this.buffered().use<BufferedReader, T>{block(it.lineIterator())} inline fun Reader.foreachLine(block: (String) -> Unit): Unit {
this.foreach{
val iter = buffered().lineIterator()
while (iter.hasNext) {
val elem = iter.next()
block(elem)
}
}
}
inline fun <T> Reader.useLines(block: (Iterator<String>) -> T): T = this.buffered().foreach<BufferedReader, T>{block(it.lineIterator())}
/** /**
* Returns an iterator over each line. * Returns an iterator over each line.
* <b>Note</b> the caller must close the underlying <code>BufferedReader</code> * <b>Note</b> the caller must close the underlying <code>BufferedReader</code>
+32 -9
View File
@@ -19,11 +19,12 @@ class IoTest() : TestSupport() {
} }
fun sample() : Reader { fun sample() : Reader {
return StringReader("""Hello return StringReader("Hello\nWorld");
World""");
} }
fun testLineIterator() { fun testLineIterator() {
// TODO we should maybe zap the useLines approach as it encourages
// use of iterators which don't close the underlying stream
val list1 = sample().useLines{it.toArrayList()} val list1 = sample().useLines{it.toArrayList()}
val list2 = sample().useLines<ArrayList<String>>{it.toArrayList()} val list2 = sample().useLines<ArrayList<String>>{it.toArrayList()}
@@ -31,20 +32,42 @@ World""");
assertEquals(arrayList("Hello", "World"), list2) assertEquals(arrayList("Hello", "World"), list2)
} }
fun testUse() { fun testForEach() {
/**
val list = ArrayList<String>() val list = ArrayList<String>()
val reader = sample().buffered() val reader = sample().buffered()
TODO compiler error? reader.foreach{
reader.use{ while (true) {
val line = it.readLine() val line = it.readLine()
if (line != null) { if (line != null)
list.add(line) list.add(line)
else
break
} }
} }
assertEquals(arrayList("Hello", "World"), list) assertEquals(arrayList("Hello", "World"), list)
}
fun testForEachLine() {
val list = ArrayList<String>()
val reader = sample()
/* TODO would be nicer maybe to write this as
reader.lines.foreach { ... }
as we could one day maybe one day write that as
for (line in reader.lines)
if the for(elem in thing) {...} statement could act as syntax sugar for
thing.foreach{ elem -> ... }
if thing is not an Iterable/array/Iterator but has a suitable foreach method
*/ */
reader.foreachLine{
list.add(it)
}
assertEquals(arrayList("Hello", "World"), list)
} }
} }