Skip to content

Commit 1f2254d

Browse files
qwwdfsadpablobaxter
authored andcommitted
Introduce runningFold operator, make scan alias to runningFold (Kotlin#2645)
* Otherwise Kotlin users with non-reactive background get confused by flow/stdlib inconsistency * Make it experimental to delay the final decision about the name Fixes Kotlin#2641
1 parent 954503e commit 1f2254d

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

Diff for: kotlinx-coroutines-core/api/kotlinx-coroutines-core.api

+1
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,7 @@ public final class kotlinx/coroutines/flow/FlowKt {
994994
public static synthetic fun retry$default (Lkotlinx/coroutines/flow/Flow;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
995995
public static synthetic fun retry$default (Lkotlinx/coroutines/flow/Flow;JLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
996996
public static final fun retryWhen (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function4;)Lkotlinx/coroutines/flow/Flow;
997+
public static final fun runningFold (Lkotlinx/coroutines/flow/Flow;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow;
997998
public static final fun runningReduce (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow;
998999
public static final fun sample (Lkotlinx/coroutines/flow/Flow;J)Lkotlinx/coroutines/flow/Flow;
9991000
public static final fun sample-HG0u8IE (Lkotlinx/coroutines/flow/Flow;D)Lkotlinx/coroutines/flow/Flow;

Diff for: kotlinx-coroutines-core/common/src/flow/operators/Transform.kt

+16-2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ public fun <T> Flow<T>.onEach(action: suspend (T) -> Unit): Flow<T> = transform
7474
return@transform emit(value)
7575
}
7676

77+
/**
78+
* Folds the given flow with [operation], emitting every intermediate result, including [initial] value.
79+
* Note that initial value should be immutable (or should not be mutated) as it is shared between different collectors.
80+
* For example:
81+
* ```
82+
* flowOf(1, 2, 3).scan(emptyList<Int>()) { acc, value -> acc + value }.toList()
83+
* ```
84+
* will produce `[], [1], [1, 2], [1, 2, 3]]`.
85+
*
86+
* This function is an alias to [runningFold] operator.
87+
*/
88+
@ExperimentalCoroutinesApi
89+
public fun <T, R> Flow<T>.scan(initial: R, @BuilderInference operation: suspend (accumulator: R, value: T) -> R): Flow<R> = runningFold(initial, operation)
90+
7791
/**
7892
* Folds the given flow with [operation], emitting every intermediate result, including [initial] value.
7993
* Note that initial value should be immutable (or should not be mutated) as it is shared between different collectors.
@@ -84,7 +98,7 @@ public fun <T> Flow<T>.onEach(action: suspend (T) -> Unit): Flow<T> = transform
8498
* will produce `[], [1], [1, 2], [1, 2, 3]]`.
8599
*/
86100
@ExperimentalCoroutinesApi
87-
public fun <T, R> Flow<T>.scan(initial: R, @BuilderInference operation: suspend (accumulator: R, value: T) -> R): Flow<R> = flow {
101+
public fun <T, R> Flow<T>.runningFold(initial: R, @BuilderInference operation: suspend (accumulator: R, value: T) -> R): Flow<R> = flow {
88102
var accumulator: R = initial
89103
emit(accumulator)
90104
collect { value ->
@@ -100,7 +114,7 @@ public fun <T, R> Flow<T>.scan(initial: R, @BuilderInference operation: suspend
100114
*
101115
* For example:
102116
* ```
103-
* flowOf(1, 2, 3, 4).runningReduce { (v1, v2) -> v1 + v2 }.toList()
117+
* flowOf(1, 2, 3, 4).runningReduce { acc, value -> acc + value }.toList()
104118
* ```
105119
* will produce `[1, 3, 6, 10]`
106120
*/

Diff for: kotlinx-coroutines-core/common/test/flow/operators/ScanTest.kt

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ class ScanTest : TestBase() {
2323
assertEquals(listOf(emptyList(), listOf(1), listOf(1, 2), listOf(1, 2, 3)), result)
2424
}
2525

26+
@Test
27+
fun testFoldWithInitial() = runTest {
28+
val flow = flowOf(1, 2, 3)
29+
val result = flow.runningFold(emptyList<Int>()) { acc, value -> acc + value }.toList()
30+
assertEquals(listOf(emptyList(), listOf(1), listOf(1, 2), listOf(1, 2, 3)), result)
31+
}
32+
2633
@Test
2734
fun testNulls() = runTest {
2835
val flow = flowOf(null, 2, null, null, null, 5)

0 commit comments

Comments
 (0)