diff --git a/libraries/stdlib/src/generated/_Aggregates.kt b/libraries/stdlib/src/generated/_Aggregates.kt index 3c50daa19c4..6b4808c7ad3 100644 --- a/libraries/stdlib/src/generated/_Aggregates.kt +++ b/libraries/stdlib/src/generated/_Aggregates.kt @@ -2122,10 +2122,51 @@ public inline fun String.none(predicate: (Char) -> Boolean): Boolean { /** * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element */ -public inline fun Array.reduce(operation: (T, T) -> T): T { +public inline fun Array.reduce(operation: (S, T) -> S): S { val iterator = this.iterator() if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") - var accumulator = iterator.next() + var accumulator: S = iterator.next() + while (iterator.hasNext()) { + accumulator = operation(accumulator, iterator.next()) + } + return accumulator +} + +/** + * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element + */ +public inline fun Iterable.reduce(operation: (S, T) -> S): S { + val iterator = this.iterator() + if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") + var accumulator: S = iterator.next() + while (iterator.hasNext()) { + accumulator = operation(accumulator, iterator.next()) + } + return accumulator +} + +/** + * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element + */ +public inline fun Sequence.reduce(operation: (S, T) -> S): S { + val iterator = this.iterator() + if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") + var accumulator: S = iterator.next() + while (iterator.hasNext()) { + accumulator = operation(accumulator, iterator.next()) + } + return accumulator +} + + +deprecated("Migrate to using Sequence and respective functions") +/** + * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element + */ +public inline fun Stream.reduce(operation: (S, T) -> S): S { + val iterator = this.iterator() + if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") + var accumulator: S = iterator.next() while (iterator.hasNext()) { accumulator = operation(accumulator, iterator.next()) } @@ -2236,47 +2277,6 @@ public inline fun ShortArray.reduce(operation: (Short, Short) -> Short): Short { return accumulator } -/** - * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element - */ -public inline fun Iterable.reduce(operation: (T, T) -> T): T { - val iterator = this.iterator() - if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") - var accumulator = iterator.next() - while (iterator.hasNext()) { - accumulator = operation(accumulator, iterator.next()) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element - */ -public inline fun Sequence.reduce(operation: (T, T) -> T): T { - val iterator = this.iterator() - if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") - var accumulator = iterator.next() - while (iterator.hasNext()) { - accumulator = operation(accumulator, iterator.next()) - } - return accumulator -} - - -deprecated("Migrate to using Sequence and respective functions") -/** - * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element - */ -public inline fun Stream.reduce(operation: (T, T) -> T): T { - val iterator = this.iterator() - if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") - var accumulator = iterator.next() - while (iterator.hasNext()) { - accumulator = operation(accumulator, iterator.next()) - } - return accumulator -} - /** * Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element */ @@ -2293,10 +2293,23 @@ public inline fun String.reduce(operation: (Char, Char) -> Char): Char { /** * Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value */ -public inline fun Array.reduceRight(operation: (T, T) -> T): T { +public inline fun Array.reduceRight(operation: (T, S) -> S): S { var index = lastIndex if (index < 0) throw UnsupportedOperationException("Empty iterable can't be reduced") - var accumulator = get(index--) + var accumulator: S = get(index--) + while (index >= 0) { + accumulator = operation(get(index--), accumulator) + } + return accumulator +} + +/** + * Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value + */ +public inline fun List.reduceRight(operation: (T, S) -> S): S { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty iterable can't be reduced") + var accumulator: S = get(index--) while (index >= 0) { accumulator = operation(get(index--), accumulator) } @@ -2407,19 +2420,6 @@ public inline fun ShortArray.reduceRight(operation: (Short, Short) -> Short): Sh return accumulator } -/** - * Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value - */ -public inline fun List.reduceRight(operation: (T, T) -> T): T { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty iterable can't be reduced") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - /** * Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value */ diff --git a/libraries/stdlib/test/collections/CollectionTest.kt b/libraries/stdlib/test/collections/CollectionTest.kt index bd0e9a7bbd3..c52fa776dae 100644 --- a/libraries/stdlib/test/collections/CollectionTest.kt +++ b/libraries/stdlib/test/collections/CollectionTest.kt @@ -151,7 +151,7 @@ class CollectionTest { // TODO replace with more accurate version when KT-5987 will be fixed // failsWith(javaClass()) { fails { - arrayListOf().reduce { a, b -> a + b } + run { arrayListOf().reduce { a, b -> a + b } } } } @@ -164,7 +164,7 @@ class CollectionTest { // TODO replace with more accurate version when KT-5987 will be fixed // failsWith(javaClass()) { fails { - arrayListOf().reduceRight { a, b -> a + b } + run { arrayListOf().reduceRight { a, b -> a + b } } } } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt index eff616a1f16..9ecf1b99694 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt @@ -378,6 +378,7 @@ fun aggregates(): List { templates add f("reduce(operation: (T, T) -> T)") { inline(true) + exclude(ArraysOfObjects, Iterables, Sequences) doc { "Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element" } returns("T") @@ -395,10 +396,32 @@ fun aggregates(): List { } } + templates add f("reduce(operation: (S, T) -> S)") { + inline(true) + only(ArraysOfObjects, Iterables, Sequences) + + doc { "Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element" } + typeParam("S") + typeParam("T: S") + returns("S") + body { + """ + val iterator = this.iterator() + if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced") + + var accumulator: S = iterator.next() + while (iterator.hasNext()) { + accumulator = operation(accumulator, iterator.next()) + } + return accumulator + """ + } + } + templates add f("reduceRight(operation: (T, T) -> T)") { inline(true) - only(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) + only(Strings, ArraysOfPrimitives) doc { "Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value" } returns("T") body { @@ -416,6 +439,28 @@ fun aggregates(): List { } } + templates add f("reduceRight(operation: (T, S) -> S)") { + inline(true) + + only(Lists, ArraysOfObjects) + doc { "Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value" } + typeParam("S") + typeParam("T: S") + returns("S") + body { + """ + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty iterable can't be reduced") + + var accumulator: S = get(index--) + while (index >= 0) { + accumulator = operation(get(index--), accumulator) + } + + return accumulator + """ + } + } templates add f("forEach(operation: (T) -> Unit)") { inline(true)