Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Combine values in parallel

reduce_tree combines adjacent pairs on the pool, then combines their results. The function takes two values and returns either one value or a Result of that value type. Give arithmetic callbacks their own fallible contract.

def add[T: IntType](left: T, right: T) -> Result[T, OverflowError[T]]:
    Ok(left + right)

def main() -> Result[(), AllocError | IoError | PoolMapError | PoolError | OverflowError[i64]]:
    with ThreadPoolExecutor(2, 2)? as pool:
        print(pool.reduce_tree(add, range(1, 6))?)?
        print(pool.reduce_tree(add, range(0))?)?
    Ok(())
Option[i64].Some(15)
Option[i64].Nothing

Empty input returns Nothing; otherwise the result is Some(value). The outer Result reports allocation failure, a closed pool, or the callback’s precise error. A fallible callback gives Result[Option[T], PoolMapError | E]. Lists are consumed without copying their elements; ranges remain ordinary copyable values.

The tree is fixed: [a, b, c, d, e] becomes [f(a, b), f(c, d), e], then [f(f(a, b), f(c, d)), e], then one value. More workers do not change that grouping. An odd final element advances unchanged.

Choose an operation whose grouping is suitable for your task. Subtraction and floating-point addition can give different answers from a serial left-to-right loop. Keep a serial loop when that exact order matters. Worker side effects need not follow the tree order. For fallible callbacks, errors are selected by tree level, then by left-to-right pair, not by completion time. Already accepted jobs finish before the error returns; later levels do not run. Fallible callbacks use one synchronization round per tree level rather than the multi-level jobs available to infallible callbacks.

For larger inputs, reduction allocates scratch storage proportional to the input length and only a bounded window of jobs. Empty and singleton reductions allocate nothing. If allocation fails, the operation waits for accepted jobs and cleans up every intermediate value before returning.