From fee6bed2d473b762f54ef7ef09aa675d534ae1ec Mon Sep 17 00:00:00 2001 From: James Strachan Date: Tue, 20 Dec 2011 16:28:18 +0000 Subject: [PATCH] removed the create() methods; added linkedList(varargs) helper method and made filter/flatMap/map all allow an optional argument for the kind of collection to filter/flatMap/map into. I've temporarily commented out Alex's implementation of Iterable.filter in Filters.kt as I was getting all kinds of compile error messages. Will discuss this on the list & how better to organise the functions into files --- stdlib/ktSrc/Filter.kt | 4 ++++ stdlib/ktSrc/JavaUtil.kt | 44 ++++++++++------------------------ testlib/test/CollectionTest.kt | 34 ++++++++++++++++++++++++-- testlib/test/ListTest.kt | 1 + testlib/test/SetTest.kt | 1 + 5 files changed, 50 insertions(+), 34 deletions(-) diff --git a/stdlib/ktSrc/Filter.kt b/stdlib/ktSrc/Filter.kt index 4d5870476d9..1fa5cb45317 100644 --- a/stdlib/ktSrc/Filter.kt +++ b/stdlib/ktSrc/Filter.kt @@ -11,6 +11,7 @@ inline fun java.util.Iterator.filter(f: fun(T): Boolean) : java.util.Iter /* Adds filtered elements in to given container */ +/* inline fun > java.lang.Iterable.filterTo(var container: U, filter: fun(T): Boolean) : U { for(element in this) { if(filter(element)) @@ -18,11 +19,14 @@ inline fun > java.lang.Iterable.filterTo(var container } return container } +*/ /* Create iterator filtering given java.lang.Iterable */ +/* inline fun java.lang.Iterable.filter(f: fun(T): Boolean) : java.util.Iterator = (iterator() as java.util.Iterator).filter(f) +*/ private class FilterIterator(val original: java.util.Iterator, val filter: fun(T): Boolean) : java.util.Iterator { var state = 0 diff --git a/stdlib/ktSrc/JavaUtil.kt b/stdlib/ktSrc/JavaUtil.kt index 4f50c7afb62..c9ef555cf0d 100644 --- a/stdlib/ktSrc/JavaUtil.kt +++ b/stdlib/ktSrc/JavaUtil.kt @@ -18,6 +18,14 @@ inline fun arrayList(vararg values: T) : ArrayList { return answer; } +/** Returns a new LinkedList with a variable number of initial elements */ +inline fun linkedList(vararg values: T) : LinkedList { + val answer = LinkedList() + for (v in values) + answer.add(v) + return answer; +} + /** Returns a new HashSet with a variable number of initial elements */ inline fun hashSet(vararg values: T) : HashSet { val answer = HashSet() @@ -26,25 +34,6 @@ inline fun hashSet(vararg values: T) : HashSet { return answer; } -/** Returns a new collection for the results of a helper method */ -protected fun java.lang.Iterable.create(defaultSize: Int? = null) : Collection { - if (defaultSize != null) { - return ArrayList(defaultSize) - } else { - return ArrayList() - } -} - -protected fun Set.create(defaultSize: Int? = null) : Set { - if (defaultSize != null) { - return HashSet(defaultSize) - } else { - return HashSet() - } -} - - - /** Returns true if any elements in the collection match the given predicate */ inline fun java.lang.Iterable.any(predicate: fun(T): Boolean) : Boolean { for (elem in this) { @@ -75,26 +64,19 @@ inline fun java.lang.Iterable.find(predicate: fun(T): Boolean) : T? { } /** Returns a new collection containing all elements in this collection which match the given predicate */ -// TODO using: Collection for the return type - I wonder if this exact type could be -// deduced somewhat from the This.Type; e.g. returning Set on a Set, Array on Array etc -/* -inline fun java.lang.Iterable.filter(predicate: fun(T): Boolean) : Collection { - val result = this.create() +inline fun java.lang.Iterable.filter(result: Collection = ArrayList(), predicate: fun(T): Boolean) : Collection { for (elem in this) { if (predicate(elem)) result.add(elem) } return result } -*/ /** * Returns the result of transforming each item in the collection to a one or more values which * are concatenated together into a single collection */ -// TODO should use Iterable instead of Collection in transform? -inline fun java.lang.Iterable.flatMap(transform: fun(T): Collection) : Collection { - val result = this.create() +inline fun java.lang.Iterable.flatMap(result: Collection = ArrayList(), transform: fun(T): Collection) : Collection { for (elem in this) { val coll = transform(elem) if (coll != null) { @@ -128,16 +110,14 @@ inline fun java.lang.Iterable.join(separator: String, prefix: String = "" } /** Returns a new collection containing the results of applying the given function to each element in this collection */ -inline fun java.lang.Iterable.map(transform : fun(T) : R) : Collection { - val result = this.create() +inline fun java.lang.Iterable.map(result: Collection = ArrayList(), transform : fun(T) : R) : Collection { for (item in this) result.add(transform(item)) return result } /** Returns a new collection containing the results of applying the given function to each element in this collection */ -inline fun java.util.Collection.map(transform : fun(T) : R) : Collection { - val result = this.create(this.size) +inline fun java.util.Collection.map(result: Collection = ArrayList(this.size), transform : fun(T) : R) : Collection { for (item in this) result.add(transform(item)) return result diff --git a/testlib/test/CollectionTest.kt b/testlib/test/CollectionTest.kt index 8882fa699ac..3768820f61a 100644 --- a/testlib/test/CollectionTest.kt +++ b/testlib/test/CollectionTest.kt @@ -1,11 +1,11 @@ namespace test.collections -import std.test.* - // TODO can we avoid importing all this stuff by default I wonder? // e.g. making println and the collection builder methods public by default? +import std.* import std.io.* import std.util.* +import std.test.* import java.util.* class CollectionTest() : TestSupport() { @@ -39,6 +39,36 @@ class CollectionTest() : TestSupport() { assertEquals(arrayList("foo"), foo) } + fun testFilterIntoLinkedList() { + // TODO would be nice to avoid the + val foo = data.filter(linkedList()){it.startsWith("f")} + + assert { + foo.all{it.startsWith("f")} + } + assertEquals(1, foo.size) + assertEquals(linkedList("foo"), foo) + + assert { + foo is LinkedList + } + } + + fun testFilterIntoSortedSet() { + // TODO would be nice to avoid the + val foo = data.filter(hashSet()){it.startsWith("f")} + + assert { + foo.all{it.startsWith("f")} + } + assertEquals(1, foo.size) + assertEquals(hashSet("foo"), foo) + + assert { + foo is HashSet + } + } + fun testFind() { val x = data.find{it.startsWith("x")} assertNull(x) diff --git a/testlib/test/ListTest.kt b/testlib/test/ListTest.kt index fc041d4362c..85ea7007ba9 100644 --- a/testlib/test/ListTest.kt +++ b/testlib/test/ListTest.kt @@ -4,6 +4,7 @@ import std.test.* // TODO can we avoid importing all this stuff by default I wonder? // e.g. making println and the collection builder methods public by default? +import std.* import std.io.* import std.util.* import java.util.* diff --git a/testlib/test/SetTest.kt b/testlib/test/SetTest.kt index cdc8f12d586..3ae835dd029 100644 --- a/testlib/test/SetTest.kt +++ b/testlib/test/SetTest.kt @@ -1,5 +1,6 @@ namespace test.collections +import std.* import std.io.* import std.util.* import std.test.*