From 939f0e908540d48e4193b2cfbed37eac36c965ab Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 23 May 2012 09:35:16 +0100 Subject: [PATCH] added drop(n) and dropWhile(predicates) for KT-2067 - also tail() now returns the usual idea of tail() - namely everything but the head - rather than just the last element. Finally added more test sample code to the kdoc --- libraries/stdlib/ReadMe.md | 14 +++++ libraries/stdlib/src/kotlin/JLangIterables.kt | 14 +++++ .../stdlib/src/kotlin/JLangIterablesLazy.kt | 20 +++++++ .../src/kotlin/JLangIterablesSpecial.kt | 2 + libraries/stdlib/src/kotlin/JUtil.kt | 35 +++++++++-- libraries/stdlib/test/CollectionTest.kt | 23 ++++++++ libraries/stdlib/test/ListTest.kt | 59 ++++++++++--------- 7 files changed, 133 insertions(+), 34 deletions(-) create mode 100644 libraries/stdlib/ReadMe.md diff --git a/libraries/stdlib/ReadMe.md b/libraries/stdlib/ReadMe.md new file mode 100644 index 00000000000..94f0f34bd9f --- /dev/null +++ b/libraries/stdlib/ReadMe.md @@ -0,0 +1,14 @@ +## The Kotlin Standard Library + +This module creates the [standard library for kotlin](http://jetbrains.github.com/kotlin/versions/snapshot/apidocs/index.html). + +### Notes for contributors + +We use some code generation to apply the various collection-like methods to various different types like arrays, strings, kotlin.Iterable and java.lang.Iterable etc. + +To run the code generator from a kotlin checkout + + cd libraries/stdlib + mvn test-compile exec:java + +This then runs the [GenerateStandardLib.kt](https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/test/GenerateStandardLib.kt) script to create the source from the files for java.lang.Iterable and java.util.Collection etc. \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/JLangIterables.kt b/libraries/stdlib/src/kotlin/JLangIterables.kt index cee9694517d..fb663987878 100644 --- a/libraries/stdlib/src/kotlin/JLangIterables.kt +++ b/libraries/stdlib/src/kotlin/JLangIterables.kt @@ -172,6 +172,20 @@ public inline fun java.lang.Iterable.makeString(separator: String = ", ", return buffer.toString().sure() } +/** Returns a list containing the everything but the first elements that satisfy the given *predicate* */ +public inline fun > java.lang.Iterable.dropWhileTo(result: L, predicate: (T) -> Boolean) : L { + var start = true + for (element in this) { + if (start && predicate(element)) { + // ignore + } else { + start = false + result.add(element) + } + } + return result +} + /** Returns a list containing the first elements that satisfy the given *predicate* */ public inline fun > java.lang.Iterable.takeWhileTo(result: L, predicate: (T) -> Boolean) : L { for (element in this) if (predicate(element)) result.add(element) else break diff --git a/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt b/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt index 314748efd14..4ff4bc939dd 100644 --- a/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt +++ b/libraries/stdlib/src/kotlin/JLangIterablesLazy.kt @@ -79,6 +79,26 @@ public inline fun java.lang.Iterable?.requireNoNulls() : List { return list } +/** + * Returns a list containing everything but the first *n* elements + * + * @includeFunctionBody ../../test/CollectionTest.kt drop + */ +public inline fun java.lang.Iterable.drop(n: Int): List { + fun countTo(n: Int): (T) -> Boolean { + var count = 0 + return { ++count; count <= n } + } + return dropWhile(countTo(n)) +} + +/** + * Returns a list containing the everything but the first elements that satisfy the given *predicate* + * + * @includeFunctionBody ../../test/CollectionTest.kt dropWhile + */ +public inline fun java.lang.Iterable.dropWhile(predicate: (T) -> Boolean): List = dropWhileTo(ArrayList(), predicate) + /** * Returns a list containing the first *n* elements * diff --git a/libraries/stdlib/src/kotlin/JLangIterablesSpecial.kt b/libraries/stdlib/src/kotlin/JLangIterablesSpecial.kt index b50ac5cb50b..e3deca8b2b0 100644 --- a/libraries/stdlib/src/kotlin/JLangIterablesSpecial.kt +++ b/libraries/stdlib/src/kotlin/JLangIterablesSpecial.kt @@ -88,6 +88,8 @@ public fun java.lang.Iterable.contains(item : T) : Boolean { /** * Convert collection of arbitrary elements to collection of tuples of the index and the element + * + * @includeFunctionBody ../../test/ListTest.kt withIndices */ public fun java.lang.Iterable.withIndices() : java.lang.Iterable<#(Int, T)> { return object : java.lang.Iterable<#(Int, T)> { diff --git a/libraries/stdlib/src/kotlin/JUtil.kt b/libraries/stdlib/src/kotlin/JUtil.kt index 10bac18540c..200fcd37353 100644 --- a/libraries/stdlib/src/kotlin/JUtil.kt +++ b/libraries/stdlib/src/kotlin/JUtil.kt @@ -152,17 +152,40 @@ public inline fun List.sort(transform: fun(T) : java.lang.Comparable<* } */ -val List.head : T? - get() = this.get(0) - +/** + * Returns the first item in the list + * + * @includeFunctionBody ../../test/ListTest.kt first + */ val List.first : T? get() = this.head -val List.tail : T? + +/** + * Returns the last item in the list + * + * @includeFunctionBody ../../test/ListTest.kt last + */ +val List.last : T? get() { val s = this.size return if (s > 0) this.get(s - 1) else null } -val List.last : T? - get() = this.tail +/** + * Returns the first item in the list + * + * @includeFunctionBody ../../test/ListTest.kt head + */ +val List.head : T? + get() = this.get(0) + +/** + * Returns all elements in this collection apart from the first one + * + * @includeFunctionBody ../../test/ListTest.kt tail + */ +val List.tail : List + get() { + return drop(1) + } diff --git a/libraries/stdlib/test/CollectionTest.kt b/libraries/stdlib/test/CollectionTest.kt index 2c35b16e951..ae29da0b2f0 100644 --- a/libraries/stdlib/test/CollectionTest.kt +++ b/libraries/stdlib/test/CollectionTest.kt @@ -302,6 +302,29 @@ class CollectionTest { } } + test fun drop() { + val coll = arrayList("foo", "bar", "abc") + assertEquals(arrayList("bar", "abc"), coll.drop(1)) + assertEquals(arrayList("abc"), coll.drop(2)) + } + + test fun dropWhile() { + val coll = arrayList("foo", "bar", "abc") + assertEquals(arrayList("bar", "abc"), coll.dropWhile{ it.startsWith("f") }) + } + + test fun take() { + val coll = arrayList("foo", "bar", "abc") + assertEquals(arrayList("foo"), coll.take(1)) + assertEquals(arrayList("foo", "bar"), coll.take(2)) + } + + test fun takeWhile() { + val coll = arrayList("foo", "bar", "abc") + assertEquals(arrayList("foo"), coll.takeWhile{ it.startsWith("f") }) + assertEquals(arrayList("foo", "bar", "abc"), coll.takeWhile{ it.size == 3 }) + } + test fun toArray() { val data = arrayList("foo", "bar") val arr = data.toArray() diff --git a/libraries/stdlib/test/ListTest.kt b/libraries/stdlib/test/ListTest.kt index c427d46f647..97136d5a993 100644 --- a/libraries/stdlib/test/ListTest.kt +++ b/libraries/stdlib/test/ListTest.kt @@ -1,36 +1,39 @@ package test.collections import kotlin.test.* - -import org.junit.Test +import org.junit.Test as test class ListTest { - val data = arrayList("foo", "bar") - Test fun headAndTail() { - val h = data.head - assertEquals("foo", h) - - val t = data.tail - assertEquals("bar", t) - } - - Test fun firstAndLast() { - val h = data.first - assertEquals("foo", h) - - val t = data.last - assertEquals("bar", t) - } - - Test fun withIndices() { - val withIndices = data.withIndices() - var index = 0 - for (withIndex in withIndices) { - assertEquals(withIndex._1, index) - assertEquals(withIndex._2, data[index]) - index++ + test fun head() { + val data = arrayList("foo", "bar") + assertEquals("foo", data.head) + } + + test fun tail() { + val data = arrayList("foo", "bar", "whatnot") + assertEquals(arrayList("bar", "whatnot"), data.tail) + } + + test fun first() { + val data = arrayList("foo", "bar") + assertEquals("foo", data.first) + } + + test fun last() { + val data = arrayList("foo", "bar") + assertEquals("bar", data.last) + } + + test fun withIndices() { + val data = arrayList("foo", "bar") + val withIndices = data.withIndices() + var index = 0 + for (withIndex in withIndices) { + assertEquals(withIndex._1, index) + assertEquals(withIndex._2, data[index]) + index++ + } + assertEquals(data.size(), index) } - assertEquals(data.size(), index) - } }