# reduce: Reduce a list to a single value by iteratively applying a... In tidyverse/purrr: Functional Programming Tools

## Description

`reduce()` is an operation that combines the elements of a vector into a single value. The combination is driven by `.f`, a binary function that takes two values and returns a single value: reducing `f` over `1:3` computes the value `f(f(1, 2), 3)`.

## Usage

 ```1 2 3``` ```reduce(.x, .f, ..., .init, .dir = c("forward", "backward")) reduce2(.x, .y, .f, ..., .init) ```

## Arguments

 `.x` A list or atomic vector. `.f` For `reduce()`, and `accumulate()`, a 2-argument function. The function will be passed the accumulated value as the first argument and the "next" value as the second argument. For `reduce2()` and `accumulate2()`, a 3-argument function. The function will be passed the accumulated value as the first argument, the next value of `.x` as the second argument, and the next value of `.y` as the third argument. The reduction terminates early if `.f` returns a value wrapped in a `done()`. `...` Additional arguments passed on to the mapped function. `.init` If supplied, will be used as the first value to start the accumulation, rather than using `x[[1]]`. This is useful if you want to ensure that `reduce` returns a correct value when `.x` is empty. If missing, and `x` is empty, will throw an error. `.dir` The direction of reduction as a string, one of `"forward"` (the default) or `"backward"`. See the section about direction below. `.y` For `reduce2()` and `accumulate2()`, an additional argument that is passed to `.f`. If `init` is not set, `.y` should be 1 element shorter than `.x`.

## Direction

When `.f` is an associative operation like `+` or `c()`, the direction of reduction does not matter. For instance, reducing the vector `1:3` with the binary function `+` computes the sum `((1 + 2) + 3)` from the left, and the same sum `(1 + (2 + 3))` from the right.

In other cases, the direction has important consequences on the reduced value. For instance, reducing a vector with `list()` from the left produces a left-leaning nested list (or tree), while reducing `list()` from the right produces a right-leaning list.

## Life cycle

`reduce_right()` is soft-deprecated as of purrr 0.3.0. Please use the `.dir` argument of `reduce()` instead. Note that the algorithm has changed. Whereas `reduce_right()` computed `f(f(3, 2), 1)`, `reduce(.dir = \"backward\")` computes `f(1, f(2, 3))`. This is the standard way of reducing from the right.

To update your code with the same reduction as `reduce_right()`, simply reverse your vector and use a left reduction:

 ```1 2 3 4 5``` ```# Before: reduce_right(1:3, f) # After: reduce(rev(1:3), f) ```

`reduce2_right()` is soft-deprecated as of purrr 0.3.0 without replacement. It is not clear what algorithmic properties should a right reduction have in this case. Please reach out if you know about a use case for a right reduction with a ternary function.

`accumulate()` for a version that returns all intermediate values of the reduction.
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49``` ```# Reducing `+` computes the sum of a vector while reducing `*` # computes the product: 1:3 %>% reduce(`+`) 1:10 %>% reduce(`*`) # When the operation is associative, the direction of reduction # does not matter: reduce(1:4, `+`) reduce(1:4, `+`, .dir = "backward") # However with non-associative operations, the reduced value will # be different as a function of the direction. For instance, # `list()` will create left-leaning lists when reducing from the # right, and right-leaning lists otherwise: str(reduce(1:4, list)) str(reduce(1:4, list, .dir = "backward")) # reduce2() takes a ternary function and a second vector that is # one element smaller than the first vector: paste2 <- function(x, y, sep = ".") paste(x, y, sep = sep) letters[1:4] %>% reduce(paste2) letters[1:4] %>% reduce2(c("-", ".", "-"), paste2) x <- list(c(0, 1), c(2, 3), c(4, 5)) y <- list(c(6, 7), c(8, 9)) reduce2(x, y, paste) # You can shortcircuit a reduction and terminate it early by # returning a value wrapped in a done(). In the following example # we return early if the result-so-far, which is passed on the LHS, # meets a condition: paste3 <- function(out, input, sep = ".") { if (nchar(out) > 4) { return(done(out)) } paste(out, input, sep = sep) } letters %>% reduce(paste3) # Here the early return branch checks the incoming inputs passed on # the RHS: paste4 <- function(out, input, sep = ".") { if (input == "j") { return(done(out)) } paste(out, input, sep = sep) } letters %>% reduce(paste4) ```