# funprog: Common Higher-Order Functions in Functional Programming...

## 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` and `Position` 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

 ```1 2 3 4 5 6``` ```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

 `f` a function of the appropriate arity (binary for `Reduce`, unary for `Filter`, `Find` and `Position`, k-ary for `Map` if this is called with k arguments). An arbitrary predicate function for `Negate`. `x` a vector. `init` an R object of the same kind as the elements of `x`. `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. `nomatch` the value to be returned in the case when “no match” (no element satisfying the predicate) is found. `...` vectors.

## 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.

Function `clusterMap` and `mcmapply` (not Windows) in package parallel provide parallel versions of `Map`.
 ``` 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 50``` ```## 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 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())) ```