% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/reduce.R
\name{reduce}
\alias{reduce}
\alias{reduce2}
\title{Reduce a list to a single value by iteratively applying a binary function}
\usage{
reduce(.x, .f, ..., .init, .dir = c("forward", "backward"))

reduce2(.x, .y, .f, ..., .init)
}
\arguments{
\item{.x}{A list or atomic vector.}

\item{.f}{For \code{reduce()}, 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 \code{reduce2()}, a 3-argument function. The function will be passed the
accumulated value as the first argument, the next value of \code{.x} as the
second argument, and the next value of \code{.y} as the third argument.

The reduction terminates early if \code{.f} returns a value wrapped in
a \code{\link[=done]{done()}}.}

\item{...}{Additional arguments passed on to the reduce function.

We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:

\if{html}{\out{<div class="sourceCode R">}}\preformatted{# Instead of
x |> reduce(f, 1, 2, collapse = ",")
# do:
x |> reduce(\\(x, y) f(x, y, 1, 2, collapse = ","))
}\if{html}{\out{</div>}}

This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}

\item{.init}{If supplied, will be used as the first value to start
the accumulation, rather than using \code{.x[[1]]}. This is useful if
you want to ensure that \code{reduce} returns a correct value when \code{.x}
is empty. If missing, and \code{.x} is empty, will throw an error.}

\item{.dir}{The direction of reduction as a string, one of
\code{"forward"} (the default) or \code{"backward"}. See the section about
direction below.}

\item{.y}{For \code{reduce2()} an additional
argument that is passed to \code{.f}. If \code{init} is not set, \code{.y}
should be 1 element shorter than \code{.x}.}
}
\description{
\code{reduce()} is an operation that combines the elements of a vector
into a single value. The combination is driven by \code{.f}, a binary
function that takes two values and returns a single value: reducing
\code{f} over \code{1:3} computes the value \code{f(f(1, 2), 3)}.
}
\section{Direction}{


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

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

\examples{
# Reducing `+` computes the sum of a vector while reducing `*`
# computes the product:
1:3 |> reduce(`+`)
1:10 |> reduce(`*`)

# By ignoring the input vector (nxt), you can turn output of one step into
# the input for the next. This code takes 10 steps of a random walk:
reduce(1:10, \(acc, nxt) acc + rnorm(1), .init = 0)

# 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)
}
\seealso{
\code{\link[=accumulate]{accumulate()}} for a version that returns all intermediate
values of the reduction.
}
