I can create a compose operator in R:
`%c%` = function(x,y)function(...)x(y(...))
To be used like this:
> numericNull = is.null %c% numeric > numericNull(myVec) [2] TRUE FALSE
but I would like to know if there is an official set of functions to do this kind of thing and other operations such as currying in R. Largely this is to reduce the number of brackets, function keywords etc in my code.
My curry function:
> curry=function(...){ z1=z0=substitute(...);z1[1]=call("list"); function(...){do.call(as.character(z0[[1]]), as.list(c(eval(z1),list(...))))}} > p = curry(paste(collapse="")) > p(letters[1:10]) [1] "abcdefghij"
This is especially nice for e.g. aggregate:
> df = data.frame(l=sample(1:3,10,rep=TRUE), t=letters[1:10]) > aggregate(df$t,df["l"],curry(paste(collapse="")) %c% toupper) l x 1 1 ADG 2 2 BCH 3 3 EFIJ
Which I find much more elegant and editable than:
> aggregate(df$t, df["l"], function(x)paste(collapse="",toupper(x))) l x 1 1 ADG 2 2 BCH 3 3 EFIJ
Basically I want to know - has this already been done for R?
A curried function is a function of several arguments rewritten such that it accepts the first argument and returns a function that accepts the second argument and so on. This allows functions of several arguments to have some of their initial arguments partially applied.
Functional programming languages In R, this means that you can do many of the things with a function that you can do with a vector: you can assign them to variables, store them in lists, pass them as arguments to other functions, create them inside functions, and even return them as the result of a function.
Both of these functions actually exist in the roxygen
package (see the source code here) from Peter Danenberg (was originally based on Byron Ellis's solution on R-Help):
Curry <- function(FUN,...) { .orig = list(...); function(...) do.call(FUN,c(.orig,list(...))) } Compose <- function(...) { fs <- list(...) function(...) Reduce(function(x, f) f(x), fs, ...) }
Note the usage of the Reduce
function, which can be very helpful when trying to do functional programming in R. See ?Reduce for more details (which also covers other functions such as Map
and Filter
).
And your example of Curry (slightly different in this usage):
> library(roxygen) > p <- Curry(paste, collapse="") > p(letters[1:10]) [1] "abcdefghij"
Here's an example to show the utility of Compose
(applying three different functions to letters):
> Compose(function(x) x[length(x):1], Curry(paste, collapse=""), toupper)(letters) [1] "ZYXWVUTSRQPONMLKJIHGFEDCBA"
And your final example would work like this:
> aggregate(df[,"t"], df["l"], Compose(Curry(paste, collapse=""), toupper)) l x 1 1 ABG 2 2 DEFH 3 3 CIJ
Lastly, here's a way to do the same thing with plyr
(could also easily be done with by
or aggregate
as already shown):
> library(plyr) > ddply(df, .(l), function(df) paste(toupper(df[,"t"]), collapse="")) l V1 1 1 ABG 2 2 DEFH 3 3 CIJ
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With