Question

The function testfun1, defined below, does what I want it to do. (For the reasoning of all this, see the background info below the code example.) The question I wanted to ask you is why what I tried in testfun2 doesn't work. To me, both appear to be doing the exact same thing. As shown by the print in testfun2, the evaluation of the helper function inside testfun2 takes place in the correct environment, but the variables from the main function environment get magically passed to the helper function in testfun1, but not in testfun2. Does anyone of you know why?

helpfun <- function(){
 x <- x^2 + y^2
}

testfun1 <- function(x,y){

 xy <- x*y
 environment(helpfun) <- sys.frame(sys.nframe())
 x <- eval(as.call(c(as.symbol("helpfun"))))

 return(list(x=x,xy=xy))
}

testfun1(x = 2,y = 1:3)
## works as intended


eval.here <- function(fun){
 environment(fun) <- parent.frame()
 print(environment(fun))
 eval(as.call(c(as.symbol(fun))))
}

testfun2 <- function(x,y){
 print(sys.frame(sys.nframe()))
 xy <- x*y
 x <- eval.here("helpfun")

 return(list(x=x,xy=xy))
}

testfun2(x = 2,y = 1:3)
## helpfun can't find variable 'x' despite having the same environment as in testfun1...

Background info: I have a large R code in which I want to call helperfunctions inside my main function. They alter variables of the main function environment. The purpose of all this is mainly to unclutter my code. (Main function code is currently over 2000 lines, with many calls to various helperfunctions which themselves are 40-150 lines long...)
Note that the number of arguments to my helper functions is very high, so that the traditional explicit passing of function arguments ( "helpfun(arg1 = arg1, arg2 = arg2, ... , arg50 = arg50)") would be cumbersome and doesnt yield the uncluttering of the code that I am aiming for. Therefore, I need to pass the variables from the parent frame to the helper functions anonymously.

Was it helpful?

Solution

Use this instead:

eval.here <- function(fun){
 fun <- get(fun)
 environment(fun) <- parent.frame()
 print(environment(fun))
 fun()
}

Result:

> testfun2(x = 2,y = 1:3)

<environment: 0x0000000013da47a8>
<environment: 0x0000000013da47a8>
$x
[1]  5  8 13

$xy
[1] 2 4 6
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top