What do runningFold and runningReduce produce, and how do they relate to scan? Show how you'd build a running balance.
answer
- running* returns the whole timeline of accumulators
- runningFold → n+1 results (includes seed)
- runningReduce → n results (starts at element[0])
- scan == runningFold (alias)
- runningReduce on empty → [] (no throw)
basics
~10 sInstead of one final value, they return the list of every intermediate accumulator value. runningFold starts with your seed; runningReduce starts with the first element. scan is just another name for runningFold.
solid answer
~40 srunningFold(initial, op) returns a List of all intermediate accumulator states, beginning with initial and ending with the same value plain fold would give. So for n elements it yields n+1 results. runningReduce(op) is the reduce analogue: it starts from the first element and yields n results (no separate seed entry). scan is an alias of runningFold and scanIndexed of runningFoldIndexed (kept for FP familiarity). They're ideal for prefix sums, running balances, cumulative max, or state timelines. On Sequence they're lazy. runningFold is empty-safe (returns listOf(initial)); runningReduce on an empty source returns an empty list rather than throwing. Indexed variants (runningFoldIndexed/runningReduceIndexed) expose the position.
code
kotlin · 10 linesval prices = listOf(10, 20, 5)
val prefixSums = prices.runningFold(0) { a, p -> a + p }
// [0, 10, 30, 35]
val cumulativeMax = listOf(3, 1, 4, 1, 5)
.runningReduce { acc, x -> maxOf(acc, x) }
// [3, 3, 4, 4, 5]
println(emptyList<Int>().runningReduce { a, b -> a + b }) // []
println(emptyList<Int>().runningFold(0) { a, b -> a + b }) // [0]go deeper
Understands the result is a list of intermediate values rather than one number.
Knows the n+1 vs n element counts and that scan equals runningFold.
Picks running* for prefix-sum/running-balance problems and exploits laziness on Sequences.
Designs event-sourcing/state-replay style code around running accumulations and reasons about memory of materialized intermediates vs lazy sequences.
## What 'running' means A normal `fold`/`reduce` returns only the **final** accumulator. The `running*` family returns **every intermediate accumulator**, i.e. the whole accumulation timeline. ## runningFold ```kotlin listOf(1, 2, 3).runningFold(0) { acc, x -> acc + x } // [0, 1, 3, 6] ``` - Output starts with the **seed**, then one entry per element. - For `n` elements the result has **n + 1** items. - The last element equals what `fold(seed, op)` would return. - `scan` is a literal **alias** of `runningFold` (and `scanIndexed` ↔ `runningFoldIndexed`). ## runningReduce ```kotlin listOf(1, 2, 3).runningReduce { acc, x -> acc + x } // [1, 3, 6] ``` - Uses the **first element as the seed**, so there is no separate initial entry. - For `n` elements the result has **n** items. - On an **empty** source it returns an **empty list** (it does NOT throw, unlike `reduce`). ## Empty-source behavior (memorize) - `runningFold(seed) {}` on empty → `[seed]` (one element). - `runningReduce {}` on empty → `[]`. ## Indexed and lazy variants - `runningFoldIndexed` / `runningReduceIndexed` give `(index, acc, element)`. - On a `Sequence`, all of these are **lazy** — values are produced on demand, which is great for streaming prefix computations. ## Typical uses - **Prefix sums** for range queries. - **Running balance** of a ledger. - **Cumulative max/min** over time. - Reconstructing **state history** from a list of events. ```kotlin data class Tx(val delta: Int) val txs = listOf(Tx(100), Tx(-30), Tx(50)) val balances = txs.runningFold(0) { bal, t -> bal + t.delta } // [0, 100, 70, 120] ```
- If a list has 5 elements, how many items do runningFold and runningReduce produce?runningFold produces 6 (seed + 5), runningReduce produces 5 (first element is the initial accumulator).
- What is the relationship between scan and runningFold?They are aliases — identical behavior. scan/scanIndexed mirror runningFold/runningFoldIndexed, provided for functional-programming familiarity.
fold tells you your final bank balance; runningFold hands you the full statement showing the balance after every transaction.
saying these in an interview costs you the question
- Saying runningFold returns a single value like fold
- Thinking runningReduce includes a separate seed entry
- Claiming runningReduce throws on empty (it returns [])
- Not knowing scan and runningFold are the same