Question

I have two lists of functions that I try to combine to one list of functions (one nested in the other).

funlist=list()
funlist[[1]] <- function(x1){2*x1}
funlist[[2]] <- function(x2){3*x2}

anotherlist=list()
anotherlist[[1]]=function(y1){0.5*y1}
anotherlist[[2]]=function(y2){0.7*y2}

The lists will have the same length. Desired outcome is another function list:

finalfun=list()
finalfun[[1]] which shall be the same as funlist[[1]](anotherlist[[1]])
...

Hence, if I called finalfun[[1]](6), I would get the result "6" [2*(0.5*6)], similar to calling:

 funlist[[1]](anotherlist[[1]](6))

I tried the following to create a function that nests two input functions:

nestfun <- function(infun,outfun) {lapply(1:length(infun),function(i){outfun[[i]](infun[[i]])})}   
test=nestfun(infun=anotherlist, outfun=funlist)

Which produced an error:

Error in 2 * x1 : non-numeric argument to binary operator
Called from: lapply(1:length(infun), function(i) {
    outfun[[i]](infun[[i]])
})

What am I overlooking?

Was it helpful?

Solution

This should work:

fnest<-function(f1,f2){  
force(f1)
force(f2)
nest<-function(x) f1(f2(x))}

finalfun<-list()
finalfun<-lapply(1:length(funlist), function (i) fnest(funlist[[i]], anotherlist[[i]]) )

finalfun[[2]](10)
#21

Note that finalfun is a list of closures. The function fnest takes two functions as inputs and returns a composite function (a closure).

It's now trivial to create a function that operates on your two function lists:

nestfun<-function(funlist,anotherlist){
fnest<-function(f1,f2){  
force(f1)
force(f2)
nest<-function(x) f1(f2(x))}

finalfun<-list()
finalfun<-lapply(1:length(funlist), function (i) fnest(funlist[[i]], anotherlist[[i]]) ) }

finalfun<-list()
finalfun<-nestfun(funlist,anotherlist)

EDIT: In case people are curious about the use of force(), check out this question on lazy evaluation: Explain a lazy evaluation quirk

OTHER TIPS

Here is an approach that uses Compose from the functional package. Note, due to lazy evaluation you need to force the arguments

library(functional)
Composed <- Map(function(x, y) {
  x <- force(x)
  y <- force(y)
   Compose(y, x)}, 
 funlist,anotherlist)
# A Couple of examples
Composed[[1]](6) 
# [1] 6
Composed[[2]](6)
# [1] 12.6
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top