Rev 70394 | Rev 81157 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
% File src/library/base/man/funprog.Rd% Part of the R package, https://www.R-project.org% Copyright 1995-2016 R Core Team% Distributed under GPL 2 or later\name{funprog}\alias{Filter}\alias{Find}\alias{Map}\alias{Negate}\alias{Reduce}\alias{Position}\title{Common Higher-Order Functions in Functional Programming Languages}\description{\code{Reduce} uses a binary function to successively combine theelements of a given vector and a possibly given initial value.\code{Filter} extracts the elements of a vector for which a predicate(logical) function gives true. \code{Find} and \code{Position} givethe first or last such element and its position in the vector,respectively. \code{Map} applies a function to the correspondingelements of given vectors. \code{Negate} creates the negation of agiven function.}\usage{Reduce(f, x, init, right = FALSE, accumulate = FALSE)Filter(f, x)Find(f, x, right = FALSE, nomatch = NULL)Map(f, ...)Negate(f)Position(f, x, right = FALSE, nomatch = NA_integer_)}\arguments{\item{f}{a function of the appropriate arity (binary for\code{Reduce}, unary for \code{Filter}, \code{Find} and\code{Position}, \eqn{k}-ary for \code{Map} if this is called with\eqn{k} arguments). An arbitrary predicate function for\code{Negate}.}\item{x}{a vector.}\item{init}{an \R object of the same kind as the elements of\code{x}.}\item{right}{a logical indicating whether to proceed from left toright (default) or from right to left.}\item{accumulate}{a logical indicating whether the successive reducecombinations should be accumulated. By default, only the finalcombination is used.}\item{nomatch}{the value to be returned in the case when\dQuote{no match} (no element satisfying the predicate) is found.}\item{\dots}{vectors.}}\details{If \code{init} is given, \code{Reduce} logically adds it to the start(when proceeding left to right) or the end of \code{x}, respectively.If this possibly augmented vector \eqn{v} has \eqn{n > 1} elements,\code{Reduce} successively applies \eqn{f} to the elements of \eqn{v}from left to right or right to left, respectively. I.e., a leftreduce computes \eqn{l_1 = f(v_1, v_2)}, \eqn{l_2 = f(l_1, v_3)}, etc.,and returns \eqn{l_{n-1} = f(l_{n-2}, v_n)}, and a right reduce does\eqn{r_{n-1} = f(v_{n-1}, v_n)}, \eqn{r_{n-2} = f(v_{n-2}, r_{n-1})}and returns \eqn{r_1 = f(v_1, r_2)}. (E.g., if \eqn{v} is thesequence (2, 3, 4) and \eqn{f} is division, left and right reduce give\eqn{(2 / 3) / 4 = 1/6} and \eqn{2 / (3 / 4) = 8/3}, respectively.)If \eqn{v} has only a single element, this is returned; if there areno elements, \code{NULL} is returned. Thus, it is ensured that\code{f} is always called with 2 arguments.The current implementation is non-recursive to ensure stability andscalability.\code{Reduce} is patterned after Common Lisp's \code{reduce}. Areduce is also known as a fold (e.g., in Haskell) or an accumulate(e.g., in the C++ Standard Template Library). The accumulativeversion corresponds to Haskell's scan functions.\code{Filter} applies the unary predicate function \code{f} to eachelement of \code{x}, coercing to logical if necessary, and returns thesubset of \code{x} for which this gives true. Note that possible\code{NA} values are currently always taken as false; control over\code{NA} handling may be added in the future. \code{Filter}corresponds to \code{filter} in Haskell or \code{remove-if-not} inCommon Lisp.\code{Find} and \code{Position} are patterned after Common Lisp's\code{find-if} and \code{position-if}, respectively. If there is anelement for which the predicate function gives true, then the first orlast such element or its position is returned depending on whether\code{right} is false (default) or true, respectively. If there is nosuch element, the value specified by \code{nomatch} is returned. Thecurrent implementation is not optimized for performance.\code{Map} is a simple wrapper to \code{\link{mapply}} which does notattempt to simplify the result, similar to Common Lisp's \code{mapcar}(with arguments being recycled, however). Future versions may allowsome control of the result type.\code{Negate} corresponds to Common Lisp's \code{complement}. Given a(predicate) function \code{f}, it creates a function which returns thelogical negation of what \code{f} returns.}\seealso{Function \code{\link{clusterMap}} and \code{\link{mcmapply}} (notWindows) in package \pkg{parallel} provide parallel versions of \code{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))## 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 ascfrac(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))\donttest{## Find all objects in the base environment which are *not* functions:Filter(Negate(is.function), sapply(ls(baseenv()), get, baseenv()))}}\keyword{programming}