Provide constrainOnce extension method for the Sequence.

Sequence created from the generator function without an initial value can be iterated only once.
The same is for BufferedReader.lines sequence.
This commit is contained in:
Ilya Gorbunov
2015-04-02 22:16:51 +03:00
parent 698ffa2807
commit f2d865e836
5 changed files with 106 additions and 29 deletions
@@ -20,24 +20,24 @@ fun fibonacci(): Sequence<Int> {
public class SequenceTest {
test fun filterEmptySequence() {
val stream = sequenceOf<String>()
assertEquals(0, stream.filter { false }.count())
assertEquals(0, stream.filter { true }.count())
val sequence = sequenceOf<String>()
assertEquals(0, sequence.filter { false }.count())
assertEquals(0, sequence.filter { true }.count())
}
test fun mapEmptyStream() {
val stream = sequenceOf<String>()
assertEquals(0, stream.map { false }.count())
assertEquals(0, stream.map { true }.count())
test fun mapEmptySequence() {
val sequence = sequenceOf<String>()
assertEquals(0, sequence.map { false }.count())
assertEquals(0, sequence.map { true }.count())
}
test fun requireNoNulls() {
val stream = sequenceOf<String?>("foo", "bar")
val notNull = stream.requireNoNulls()
val sequence = sequenceOf<String?>("foo", "bar")
val notNull = sequence.requireNoNulls()
assertEquals(listOf("foo", "bar"), notNull.toList())
val streamWithNulls = sequenceOf("foo", null, "bar")
val notNull2 = streamWithNulls.requireNoNulls() // shouldn't fail yet
val sequenceWithNulls = sequenceOf("foo", null, "bar")
val notNull2 = sequenceWithNulls.requireNoNulls() // shouldn't fail yet
fails {
// should throw an exception as we have a null
notNull2.toList()
@@ -128,9 +128,9 @@ public class SequenceTest {
}
test fun plus() {
val stream = sequenceOf("foo", "bar")
val streamCheese = stream + "cheese"
assertEquals(listOf("foo", "bar", "cheese"), streamCheese.toList())
val sequence = sequenceOf("foo", "bar")
val sequenceCheese = sequence + "cheese"
assertEquals(listOf("foo", "bar", "cheese"), sequenceCheese.toList())
// lets use a mutable variable
var mi = sequenceOf("a", "b")
@@ -141,8 +141,8 @@ public class SequenceTest {
test fun plusCollection() {
val a = sequenceOf("foo", "bar")
val b = listOf("cheese", "wine")
val stream = a + b
assertEquals(listOf("foo", "bar", "cheese", "wine"), stream.toList())
val sequence = a + b
assertEquals(listOf("foo", "bar", "cheese", "wine"), sequence.toList())
// lets use a mutable variable
var ml = sequenceOf("a")
@@ -154,7 +154,7 @@ public class SequenceTest {
}
test fun iterationOverStream() {
test fun iterationOverSequence() {
var s = ""
for (i in sequenceOf(0, 1, 2, 3, 4, 5)) {
s = s + i.toString()
@@ -162,31 +162,51 @@ public class SequenceTest {
assertEquals("012345", s)
}
test fun streamFromFunction() {
test fun sequenceFromFunction() {
var count = 3
val stream = sequence {
val sequence = sequence {
count--
if (count >= 0) count else null
}
val list = stream.toList()
val list = sequence.toList()
assertEquals(listOf(2, 1, 0), list)
fails {
sequence.toList()
}
}
test fun streamFromFunctionWithInitialValue() {
test fun sequenceFromFunctionWithInitialValue() {
val values = sequence(3) { n -> if (n > 0) n - 1 else null }
val expected = listOf(3, 2, 1, 0)
assertEquals(expected, values.toList())
assertEquals(expected, values.toList(), "Iterating sequence second time yields the same result")
}
test fun makeSequenceOneTimeConstrained() {
val sequence = sequenceOf(1, 2, 3, 4)
sequence.toList()
sequence.toList()
val oneTime = sequence.constrainOnce()
oneTime.toList()
assertTrue("should fail with IllegalStateException") {
fails {
oneTime.toList()
} is IllegalStateException
}
}
private fun <T, C : MutableCollection<in T>> Sequence<T>.takeWhileTo(result: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) result.add(element) else break
return result
}
test fun streamExtensions() {
test fun sequenceExtensions() {
val d = ArrayList<Int>()
sequenceOf(0, 1, 2, 3, 4, 5).takeWhileTo(d, { i -> i < 4 })
assertEquals(4, d.size())