- A+

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[1])(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) ## [1] 0.5143953 # compose is defined in the question compose(sin, cos, tan)(pi/4) ## [1] 0.5143953 functional::Compose(tan, cos, sin)(pi/4) ## [1] 0.5143953 sin(cos(tan(pi/4))) ## [1] 0.5143953 library(magrittr) (pi/4) %>% tan %>% cos %>% sin ## [1] 0.5143953 (. %>% tan %>% cos %>% sin)(pi/4) ## [1] 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) ## [1] 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) ## [1] 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) ## [1] 0.5143953 `