From f022b617949d336280c6ace63e83f27839426042 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Tue, 3 Apr 2012 15:36:34 +0100 Subject: [PATCH] #KT-39 Fixed with eager and lazy implementations --- libraries/stdlib/src/kotlin/Iterators.kt | 30 ++++++++++- .../stdlib/src/kotlin/JLangIterablesLazy.kt | 23 +++++++++ libraries/stdlib/src/kotlin/JUtil.kt | 39 --------------- .../src/kotlin/support/AbstractIterator.kt | 50 ++++++++++++++++++- libraries/stdlib/test/CollectionTest.kt | 29 ++++++++--- .../stdlib/test/iterators/IteratorsTest.kt | 26 ++++++++++ 6 files changed, 146 insertions(+), 51 deletions(-) diff --git a/libraries/stdlib/src/kotlin/Iterators.kt b/libraries/stdlib/src/kotlin/Iterators.kt index 53a5dd04765..7eea6b7d31e 100644 --- a/libraries/stdlib/src/kotlin/Iterators.kt +++ b/libraries/stdlib/src/kotlin/Iterators.kt @@ -1,7 +1,7 @@ package kotlin -import kotlin.support.AbstractIterator -import kotlin.support.FunctionIterator +import kotlin.support.* +import java.util.Collections /** * Returns an iterator which invokes the function to calculate the next value on each iteration until the function returns *null* @@ -110,6 +110,32 @@ private class FlatMapIterator(val iterator : java.util.Iterator, val tr } } +/** + * Creates an [[Iterator]] which iterates over this iterator then the given element at the end + * + * @includeFunctionBody ../../test/iterators/IteratorsTest.kt plus + */ +public inline fun java.util.Iterator.plus(element: T): java.util.Iterator { + return CompositeIterator(this, SingleIterator(element)) +} + + +/** + * Creates an [[Iterator]] which iterates over this iterator then the following iterator + * + * @includeFunctionBody ../../test/iterators/IteratorsTest.kt plusCollection + */ +public inline fun java.util.Iterator.plus(iterator: java.util.Iterator): java.util.Iterator { + return CompositeIterator(this, iterator) +} + +/** + * Creates an [[Iterator]] which iterates over this iterator then the following collection + * + * @includeFunctionBody ../../test/iterators/IteratorsTest.kt plusCollection + */ +public inline fun java.util.Iterator.plus(collection: java.lang.Iterable): java.util.Iterator = plus(collection.iterator()) + /** * Returns an iterator containing all the non-*null* elements, lazily throwing an [[IllegalArgumentException]] if there are any null elements diff --git a/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt b/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt index 8804b1cb7d7..60acefb602e 100644 --- a/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt +++ b/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt @@ -39,6 +39,29 @@ public inline fun java.lang.Iterable?.filterNotNull() : List = filter */ public inline fun java.lang.Iterable.flatMap(transform: (T)-> Collection) : Collection = flatMapTo(ArrayList(), transform) +/** + * Creates a copy of this collection as a [[List]] with the element added at the end + * + * @includeFunctionBody ../../test/CollectionTest.kt plus + */ +public inline fun java.lang.Iterable.plus(element: T): List { + val list = to(ArrayList()) + list.add(element) + return list +} + + +/** + * Creates a copy of this collection as a [[List]] with all the elements added at the end + * + * @includeFunctionBody ../../test/CollectionTest.kt plusCollection + */ +public inline fun java.lang.Iterable.plus(elements: java.lang.Iterable): List { + val list = to(ArrayList()) + list.addAll(elements.toCollection()) + return list +} + /** * Returns a list containing all the non-*null* elements, throwing an [[IllegalArgumentException]] if there are any null elements * diff --git a/libraries/stdlib/src/kotlin/JUtil.kt b/libraries/stdlib/src/kotlin/JUtil.kt index a0514d4513f..ead01302ef4 100644 --- a/libraries/stdlib/src/kotlin/JUtil.kt +++ b/libraries/stdlib/src/kotlin/JUtil.kt @@ -53,45 +53,6 @@ public inline fun > java.lang.Iterable.toSorted public inline fun > java.lang.Iterable.toSortedList(comparator: java.util.Comparator) : List = toList().sort(comparator) -/** - * Creates a new [[List]] with the element added at the end - * - * @includeFunctionBody ../../test/CollectionTest.kt plus - */ -public inline fun java.util.Collection.plus(element: T): List { - val list = to(ArrayList()) - list.add(element) - return list -} - -/** - * Adds the element to this collection - * - * @includeFunctionBody ../../test/CollectionTest.kt plusAssign - */ -public inline fun > C.plusAssign(element: T): C { - add(element) - return this -} - -/** - * Creates a new [[List]] with the element added at the end - */ -/* -public inline fun java.util.Collection.plus(elements: java.lang.Iterable): List = toList().plusAssign(elements) -*/ - -/** - * Adds all the elements to this collection - */ -/* -public inline fun > C.plusAssign(elements: java.lang.Iterable): C { - addAll(elements.toCollection()) - return this -} -*/ - - // List APIs public inline fun > List.sort() : List { diff --git a/libraries/stdlib/src/kotlin/support/AbstractIterator.kt b/libraries/stdlib/src/kotlin/support/AbstractIterator.kt index 4ae0bb878aa..1c67ec0ad74 100644 --- a/libraries/stdlib/src/kotlin/support/AbstractIterator.kt +++ b/libraries/stdlib/src/kotlin/support/AbstractIterator.kt @@ -32,7 +32,9 @@ public abstract class AbstractIterator: java.util.Iterator { return next.sure() } - override fun remove() { throw UnsupportedOperationException() } + override fun remove() { + throw UnsupportedOperationException() + } /** Returns the next element in the iteration without advancing the iteration */ fun peek(): T { @@ -75,7 +77,7 @@ public abstract class AbstractIterator: java.util.Iterator { } /** An [[Iterator]] which invokes a function to calculate the next value in the iteration until the function returns *null* */ -class FunctionIterator(val nextFunction : () -> T?) : AbstractIterator() { +class FunctionIterator(val nextFunction: () -> T?): AbstractIterator() { override protected fun computeNext(): Unit { val next = (nextFunction)() @@ -86,3 +88,47 @@ class FunctionIterator(val nextFunction : () -> T?) : AbstractIterator() { } } } + +/** An [[Iterator]] which iterates over a number of iterators in sequence */ +class CompositeIterator(vararg iterators: java.util.Iterator): AbstractIterator() { + + val iteratorsIter = iterators.iterator() + var currentIter: java.util.Iterator? = null + + override protected fun computeNext(): Unit { + while (true) { + if (currentIter == null) { + if (iteratorsIter.hasNext) { + currentIter = iteratorsIter.next() + } else { + done() + return + } + } + val iter = currentIter + if (iter != null) { + if (iter.hasNext()) { + setNext(iter.next()) + return + } else { + currentIter = null + } + } + } + } +} + +/** A singleton [[Iterator]] which invokes once over a value */ +class SingleIterator(val value: T): AbstractIterator() { + var first = true + + override protected fun computeNext(): Unit { + if (first) { + first = false + setNext(value) + } else { + done() + } + } +} + diff --git a/libraries/stdlib/test/CollectionTest.kt b/libraries/stdlib/test/CollectionTest.kt index 5d82b637a7b..7be32f5ae7e 100644 --- a/libraries/stdlib/test/CollectionTest.kt +++ b/libraries/stdlib/test/CollectionTest.kt @@ -258,17 +258,30 @@ class CollectionTest { val list2 = list + "cheese" assertEquals(arrayList("foo", "bar"), list) assertEquals(arrayList("foo", "bar", "cheese"), list2) + + // lets use a mutable variable + var list3 = arrayList("a", "b") + list3 += "c" + assertEquals(arrayList("a", "b", "c"), list3) } - test fun plusAssign() { - var list = arrayList("foo", "bar") -/* - TODO should we have plus and plus assign work differently for collections? - see KT-1710 + /* + TODO compiler fails on this one - list += "cheese" - assertEquals(arrayList("foo", "bar", "cheese"), list) -*/ + val list = arrayList("foo", "bar") + arrayList("cheese", "wine") + */ + test fun plusCollection() { + val a = arrayList("foo", "bar") + val b = arrayList("cheese", "wine") + val list = a + b + assertEquals(arrayList("foo", "bar", "cheese", "wine"), list) + + // lets use a mutable variable + var ml = a + ml += "beer" + ml += b + ml += "z" + assertEquals(arrayList("foo", "bar", "beer", "cheese", "wine", "z"), ml) } test fun requireNoNulls() { diff --git a/libraries/stdlib/test/iterators/IteratorsTest.kt b/libraries/stdlib/test/iterators/IteratorsTest.kt index e788a658e9a..312cdc97a57 100644 --- a/libraries/stdlib/test/iterators/IteratorsTest.kt +++ b/libraries/stdlib/test/iterators/IteratorsTest.kt @@ -52,6 +52,32 @@ class IteratorsTest { assertEquals("13, 21, 34, 55, 89, ...", fibonacci().filter { it > 10 }.makeString(separator = ", ", limit = 5)) } + test fun plus() { + val iter = arrayList("foo", "bar").iterator() + val iter2 = iter + "cheese" + assertEquals(arrayList("foo", "bar", "cheese"), iter2.toList()) + + // lets use a mutable variable + var mi = arrayList("a", "b").iterator() + mi += "c" + assertEquals(arrayList("a", "b", "c"), mi.toList()) + } + + test fun plusCollection() { + val a = arrayList("foo", "bar") + val b = arrayList("cheese", "wine") + val iter = a.iterator() + b.iterator() + assertEquals(arrayList("foo", "bar", "cheese", "wine"), iter.toList()) + + // lets use a mutable variable + var ml = arrayList("a").iterator() + ml += a.iterator() + ml += "beer" + ml += b + ml += "z" + assertEquals(arrayList("a", "foo", "bar", "beer", "cheese", "wine", "z"), ml.toList()) + } + test fun requireNoNulls() { val iter = arrayList("foo", "bar").iterator() val notNull = iter.requireNoNulls()