How to concatenate/compose functions in R?
More on Curry'ing and Composing
There is partial
in package pryr
which achieves roughly the same as Curry
in package functional
but in a different way.
(Curry
creates a list of arguments and feeds it to do.call
. partial
literally creates a new function which calls the first function with default arguments set.)
In this discussion in R-devel, Luke Tierney points out some problems with Curry
("This has quite different behavior with respect to evaluation/lazy evaluation than an analogous anonymous function. In addition, do.call has some fairly strange aspect so it with respect to how it interacts with sys.xyz functions, and does not do what you want in many cases I care about when quote = FALSE, as is the default. Adding this would
create more problems than is solves."). These issues (however infrequently they might arise) are not a concern with partial
.
Other approaches to currying / partial function application:
wargs
in package dostats
(similar to partial
but has something distinctive:
wargs(mean, na.rm=TRUE)(c(1:5, NA), na.rm=FALSE)
# this works and gives NA as answer, so na.rm=FALSE overrides na.rm=TRUE
# with partial, this would result in an error:
#### formal argument "na.rm" matched by multiple actual arguments
There is %but%
in package operators
but it doesn't work with generic functions. So ...
df <- data.frame(a=c(1:5,NA), b=c(NA, 2:6))
sapply(df, mean %but% list(na.rm=TRUE))
# a b
# NA NA
# ... but2
sapply(df, sd %but% list(na.rm=TRUE))
# a b
# 1.581139 1.581139
And it has a separate mechanism for setting logical arguments:
# from the help page
grep %but% "pf" # grep, with perl and fixed set to TRUE
As for compose, there are identically named (but different) versions in both pryr
and dostats
: compose
and %.%
-- and both are different from functional:::Compose
.
Finally, I would add that pryr
includes f
which one can conveniently use instead of function
in anonymous functions.
Using magrittr
If we require(magrittr)
, then we can
sapply(x, . %>% unique %>% sum)
or even
x %>% sapply(. %>% unique %>% sum)
or evener
x %>% sapply(unique) %>% sapply(sum)
To quote from the documentation:
x %>% f
is equivalent tof(x)
x %>% f(y)
is equivalent tof(x, y)
x %>% f %>% g %>% h
is equivalent toh(g(f(x)))
For this you can use the Compose
function in the functional
package, which is available on CRAN.:
library(functional)
sapply(x, Compose(unique,sum))