funprog {base} | R Documentation |
Common Higher-Order Functions in Functional Programming Languages
Description
Reduce
uses a binary function to successively combine the elements of a given vector and a possibly given initial value.
Filter
extracts the elements of a vector for which a predicate (logical) function gives true.
Find
andPosition
give the first or last such element and its position in the vector, respectively.
Map
applies a function to the corresponding elements of given vectors.
Negate
creates the negation of a given function.
Usage
Reduce(f, x, init, right = FALSE, accumulate = FALSE, simplify = TRUE)
Filter(f, x)
Find(f, x, right = FALSE, nomatch = NULL)
Map(f, ...)
Negate(f)
Position(f, x, right = FALSE, nomatch = NA_integer_)
Arguments
f |
a function of the appropriate arity (binary for
|
x |
a vector. |
init |
an R object of the same kind as the elements of
|
right |
a logical indicating whether to proceed from left to right (default) or from right to left. |
accumulate |
a logical indicating whether the successive reduce combinations should be accumulated. By default, only the final combination is used. |
simplify |
a logical indicating whether accumulated results should be simplified (by unlisting) in case they all are length one. |
nomatch |
the value to be returned in the case when “no match” (no element satisfying the predicate) is found. |
... |
vectors to which the function is |
Details
If init
is given, Reduce
logically adds it to the start
(when proceeding left to right) or the end of x
, respectively.
If this possibly augmented vector v
has n > 1
elements,
Reduce
successively applies f
to the elements of v
from left to right or right to left, respectively. I.e., a left
reduce computes l_1 = f(v_1, v_2)
, l_2 = f(l_1, v_3)
, etc.,
and returns l_{n-1} = f(l_{n-2}, v_n)
, and a right reduce does
r_{n-1} = f(v_{n-1}, v_n)
, r_{n-2} = f(v_{n-2}, r_{n-1})
and returns r_1 = f(v_1, r_2)
. (E.g., if v
is the
sequence (2, 3, 4) and f
is division, left and right reduce give
(2 / 3) / 4 = 1/6
and 2 / (3 / 4) = 8/3
, respectively.)
If v
has only a single element, this is returned; if there are
no elements, NULL
is returned. Thus, it is ensured that
f
is always called with 2 arguments.
The current implementation is non-recursive to ensure stability and scalability.
Reduce
is patterned after Common Lisp's reduce
. A
reduce is also known as a fold (e.g., in Haskell) or an accumulate
(e.g., in the C++ Standard Template Library). The accumulative
version corresponds to Haskell's scan functions.
Filter
applies the unary predicate function f
to each
element of x
, coercing to logical if necessary, and returns the
subset of x
for which this gives true. Note that possible
NA
values are currently always taken as false; control over
NA
handling may be added in the future. Filter
corresponds to filter
in Haskell or ‘remove-if-not’ in
Common Lisp.
Find
and Position
are patterned after Common Lisp's
‘find-if’ and ‘position-if’, respectively. If there is an
element for which the predicate function gives true, then the first or
last such element or its position is returned depending on whether
right
is false (default) or true, respectively. If there is no
such element, the value specified by nomatch
is returned. The
current implementation is not optimized for performance.
Map
is a simple wrapper to mapply
which does not
attempt to simplify the result, similar to Common Lisp's mapcar
(with arguments being recycled, however). Future versions may allow
some control of the result type.
Negate
corresponds to Common Lisp's complement
. Given a
(predicate) function f
, it creates a function which returns the
logical negation of what f
returns.
See Also
Function clusterMap
and mcmapply
(not
Windows) in package parallel provide parallel versions of Map
.
Examples
## A general-purpose adder:
add <- function(x) Reduce(`+`, x)
add(list(1, 2, 3))
## Like sum(), but can also used for adding matrices etc., as it will
## use the appropriate '+' method in each reduction step.
## More generally, many generics meant to work on arbitrarily many
## arguments can be defined via reduction:
FOO <- function(...) Reduce(FOO2, list(...))
FOO2 <- function(x, y) UseMethod("FOO2")
## FOO() methods can then be provided via FOO2() methods.
## A general-purpose cumulative adder:
cadd <- function(x) Reduce(`+`, x, accumulate = TRUE)
cadd(seq_len(7))
## A simple function to compute continued fractions:
cfrac <- function(x) Reduce(function(u, v) u + 1 / v, x, right = TRUE)
## Continued fraction approximation for pi:
cfrac(c(3, 7, 15, 1, 292))
## Continued fraction approximation for Euler's number (e):
cfrac(c(2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8))
## Map() now recycles similar to basic Ops:
Map(`+`, 1, 1 : 3) ; 1 + 1:3
Map(`+`, numeric(), 1 : 3) ; numeric() + 1:3
## Iterative function application:
Funcall <- function(f, ...) f(...)
## Compute log(exp(acos(cos(0))))
Reduce(Funcall, list(log, exp, acos, cos), 0, right = TRUE)
## n-fold iterate of a function, functional style:
Iterate <- function(f, n = 1)
function(x) Reduce(Funcall, rep.int(list(f), n), x, right = TRUE)
## Continued fraction approximation to the golden ratio:
Iterate(function(x) 1 + 1 / x, 30)(1)
## which is the same as
cfrac(rep.int(1, 31))
## Computing square root approximations for x as fixed points of the
## function t |-> (t + x / t) / 2, as a function of the initial value:
asqrt <- function(x, n) Iterate(function(t) (t + x / t) / 2, n)
asqrt(2, 30)(10) # Starting from a positive value => +sqrt(2)
asqrt(2, 30)(-1) # Starting from a negative value => -sqrt(2)
## A list of all functions in the base environment:
funs <- Filter(is.function, sapply(ls(baseenv()), get, baseenv()))
## Functions in base with more than 10 arguments:
names(Filter(function(f) length(formals(f)) > 10, funs))
## Number of functions in base with a '...' argument:
length(Filter(function(f)
any(names(formals(f)) %in% "..."),
funs))
## Find all objects in the base environment which are *not* functions:
Filter(Negate(is.function), sapply(ls(baseenv()), get, baseenv()))