Improve onEach templates.

Add new functions to reference API.
Add tests for onEach
  #KT-8220
This commit is contained in:
Ilya Gorbunov
2016-10-01 03:51:59 +03:00
parent 5bde230d4a
commit dc57d69085
10 changed files with 115 additions and 14 deletions
@@ -1586,6 +1586,14 @@ public inline fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean {
return true
}
/**
* Performs the given [action] on each element and returns the collection itself afterwards.
*/
@SinceKotlin("1.1")
public inline fun <T, C : Iterable<T>> C.onEach(action: (T) -> Unit): C {
return apply { for (element in this) action(element) }
}
/**
* Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element.
*/
+8
View File
@@ -178,6 +178,14 @@ public inline fun <K, V> Map<out K, V>.none(predicate: (Map.Entry<K, V>) -> Bool
return true
}
/**
* Performs the given [action] on each entry and returns the map itself afterwards.
*/
@SinceKotlin("1.1")
public inline fun <K, V, M : Map<out K, V>> M.onEach(action: (Map.Entry<K, V>) -> Unit): M {
return apply { for (element in this) action(element) }
}
/**
* Creates an [Iterable] instance that wraps the original map returning its entries when being iterated.
*/
@@ -969,6 +969,17 @@ public inline fun <T> Sequence<T>.none(predicate: (T) -> Boolean): Boolean {
return true
}
/**
* Returns a sequence which performs the given [action] on each element of the original sequence as they pass though it.
*/
@SinceKotlin("1.1")
public fun <T> Sequence<T>.onEach(action: (T) -> Unit): Sequence<T> {
return map {
action(it)
it
}
}
/**
* Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element.
*/
@@ -1010,6 +1010,14 @@ public inline fun CharSequence.none(predicate: (Char) -> Boolean): Boolean {
return true
}
/**
* Performs the given [action] on each character and returns the char sequence itself afterwards.
*/
@SinceKotlin("1.1")
public inline fun <S : CharSequence> S.onEach(action: (Char) -> Unit): S {
return apply { for (element in this) action(element) }
}
/**
* Accumulates value starting with the first character and applying [operation] from left to right to current accumulator value and each character.
*/
@@ -192,6 +192,17 @@ abstract class IterableTests<T : Iterable<String>>(val data: T, val empty: T) {
assertEquals(6, count)
}
@Test
fun onEach() {
var count = 0
val newData = data.onEach { count += it.length }
assertEquals(6, count)
assertTrue(data === newData)
// static types test
val list: ArrayList<Int> = arrayListOf(1, 2, 3).onEach { }
}
@Test
fun contains() {
assertTrue(data.contains("foo"))
@@ -98,6 +98,19 @@ class MapTest {
assertEquals("beverage,beer,location,Mells,name,James", list.joinToString(","))
}
@Test
fun onEach() {
val map = mutableMapOf("beverage" to "beer", "location" to "Mells")
val result = StringBuilder()
val newMap = map.onEach { result.append(it.key).append("=").append(it.value).append(";") }
assertEquals("beverage=beer;location=Mells;", result.toString())
assertTrue(map === newMap)
// static types test
val m: HashMap<String, String> = hashMapOf("a" to "b").onEach { }
}
@Test fun stream() {
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
val named = map.asSequence().filter { it.key == "name" }.single()
@@ -87,6 +87,22 @@ public class SequenceTest {
assertEquals(listOf("f", "ba"), indexed)
}
@Test
fun onEach() {
var count = 0
val data = sequenceOf("foo", "bar")
val newData = data.onEach { count += it.length }
assertFalse(data === newData)
assertEquals(0, count, "onEach should be executed lazily")
data.forEach { }
assertEquals(0, count, "onEach should be executed only when resulting sequence is iterated")
val sum = newData.sumBy { it.length }
assertEquals(sum, count)
}
@Test fun filterAndTakeWhileExtractTheElementsWithinRange() {
assertEquals(listOf(144, 233, 377, 610, 987), fibonacci().filter { it > 100 }.takeWhile { it < 1000 }.toList())
}
+12
View File
@@ -753,6 +753,18 @@ class StringTest {
assertEquals(data.toString(), sb.toString())
}
@Test
fun onEach() = withOneCharSequenceArg("abcd") { data ->
val result = StringBuilder()
val newData = data.onEach { result.append(it + 1) }
assertEquals("bcde", result.toString())
assertTrue(data === newData)
// static types test
val s: String = "x".onEach { }
val sb: StringBuilder = result.onEach { }
}
@Test fun filter() {
assertEquals("acdca", ("abcdcba").filter { !it.equals('b') })