# A recursive compose function in R?

• A+
Category：Languages

I would like to create a function, "compose" in R which will compose an arbitrary number of functions given as arguments.

So far, I have accomplished this by defining a function "of" that composes two arguments and then Reducing this:

``of <- function(f,g) function(x) f(g(x)) id <- function(x) x  compose <- function(...) {   argms = c(...)   Reduce(of,argms,id) } ``

This seems to work fine, but since I'm learning R, I thought I'd try to write it in an explicit recursive style, i.e. forgoing the use of Reduce, iow the sort of thing that you would do in Scheme like this:

``(define (compose . args)   (if (null? args) identity       ((car args) (apply compose (cdr args))))) ``

I have come up against a number of obstacles, the major one at the moment seems to be that the first element of the arguments is not getting recognized as a function. My weak attempt so far:

``comp <- function(...) {   argms <- list(...)   len <- length(argms)   if(len==0) { return(id) }   else {     (argms)(do.call(comp,argms[2:len]))    } } ``

Spits out: `Error in comp(sin, cos, tan) : attempt to apply non-function`

There must be some elegant way to do this which eludes me. Any suggestions?

1) Try this:

``comp1 <- function(f, ...) {   if (missing(f)) identity   else function(x) f(comp1(...)(x)) }   # test  comp1(sin, cos, tan)(pi/4) ##  0.5143953  # compose is defined in the question compose(sin, cos, tan)(pi/4) ##  0.5143953  functional::Compose(tan, cos, sin)(pi/4) ##  0.5143953  sin(cos(tan(pi/4))) ##  0.5143953  library(magrittr) (pi/4) %>% tan %>% cos %>% sin ##  0.5143953  (. %>% tan %>% cos %>% sin)(pi/4) ##  0.5143953 ``

1a) A variation of (1) which uses `Recall` is:

``comp1a <- function(f, ...) {   if (missing(f)) identity   else {     fun <- Recall(...)     function(x) f(fun(x))   } }  comp1a(sin, cos, tan)(pi/4) ##  0.5143953 ``

2) Here is another implementation:

``comp2 <- function(f, g, ...) {   if (missing(f)) identity   else if (missing(g)) f   else Recall(function(x) f(g(x)), ...) }  comp2(sin, cos, tan)(pi/4) ##  0.5143953 ``

3) This implementation is closer to the code in the question. It makes use of `of` defined in the question:

``comp3 <- function(...) {   if(...length() == 0) identity   else of(..1, do.call("comp3", list(...)[-1])) } comp3(sin, cos, tan)(pi/4) ##  0.5143953 ``