fcp {fcp} | R Documentation |
Function Composition
Description
Given calls f(., a=A)
and g(., b=B)
, compose function(.) g(f(., a=A), b=B)
.
Usage
fcp(f, g) # or f %.% g
f %.% g
Arguments
f |
left–operand: inner call to giver a result first. |
g |
right-operand: outer call to receirve that result. |
Details
By default, fcp
is asigned to operator %.%
so a final function can be
constructed from a chain of more than two calls, just like a chain of
|> without input or a chain of %>% with .
as the special input.
fcp
is best used to quickly create anonymous functions from existing ones
as input of functional programming tools like base::apply, base::sapply,
and base::lapply, etc. Should the composed function be saved for reuse, its
body shall retain the original syntax of component function calls as closely
as possible.
Like %>%, fcp
allows a downstream call to use .
to refer
to input from its immediate upstream call, and pipe the input into any slot
in the downstream call's list of arguments while transforming the same input
through expressions of .
; when no transformation is needed, fcp
allows
unchanged input be piped into all empty slots in the argument list (e.g.,
fun(x=1, y=, z=2) for named slots, or fun(1, , z=2) for positinal slots).
Like %>%, when no explicit reference to the output of the uptream call is used, the results is then piped into the first available positional argument of the downstream call, and a call with a lone input can be shorterned to function names without parentheses.
Later calls in a fcp
chain can refer to earlier calls by numerical symbols,
so n
refers to the result of nth call in the chain and0
refers to initial
input, allowing more flexablity than a strice "upstream to downstream" pipe.
Value
composite function g(f(x, ...), ...)
Examples
## ex1: match and extract date (pipe the initial input at differnt stage).
x <- c("2023-01-01", "2022/12/31", "2002-07-02")
p <- "^([0-9]{2,4})[-/]([0-9]{1,2})[-/]([0-9]{1,2})$"
## reference usage: input x appeared twice
(a0 <- do.call(rbind, regmatches(x, regexec(p, x))))
## composed function 1: blank as input from upstream, `0` as initial input.
(f1 <- regexec(p, ) %.% regmatches(`0`, ) %.% do.call(rbind, ))
(a1 <- f1(x))
## composed function 2: dot refer to upstream, `0` as initial input.
(f2 <- regexec(p, .) %.% regmatches(`0`, .) %.% do.call(rbind, .))
(a2 <- f2(x))
## composed function 3: use of named argument, `0` as initial input.
(f3 <- regexec(pa=p) %.% regmatches(x =`0`) %.% do.call(wh=rbind))
(a3 <- f3(x))
## ex2: date given days since 2000-010-1 (shorthand form of function calls)
(g1 <- as.Date(origin="2000-01-01") %.% f2()) # reused composed `f2`
(b1 <- g1(364))
(g2 <- as.Date(origin="2000-01-01") %.% f2) # omit ()
(b2 <- g2(364))
## ex3: wrap, pad, and upcase the strings (`sapply` uses composed function)
words <- c("Hellow World!", "Good Morning!")
s0 <- sapply(words, function(x)
{
toupper(paste(format(strwrap(x, 8), w=12, just="c"), collapse="\n"))
})
cat(s0, sep="\n---- s0 ----\n")
s1 <- sapply(words, strwrap(8) %.% format(w=12, just="c") %.%
paste(collapse="\n") %.% toupper)
cat(s1, sep="\n---- s1 ----\n")
## check equivalance
all(a1==a0) && all(a2==a0) && all(a3==a0) && all(b1==b2) && all(s1==s0)