I'm having trouble understanding how to work with nested function calls and argument evaluations.
Here is a simple example. I have a top-level function topfunction with one numeric argument. Inside the topfunction I call another lowerfunction , whose argument is to call the function defined inside the lowerfunction .
topfunction<-function(x){ lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3])) } lowerfunction<-function(mycall){ myfun<-function(first,second=0,third=NULL){ print(first) print(second) print(third) } mc<-match.call(definition = myfun, call = match.call()[[2]]) eval(mc) }
Inside the lowerfunction I capture a function call with match.call and try to evaluate the call. But since the variable x is defined only in the topfunction environment, the evaluation is not performed:
topfunction(x=1:3) Error in print(first) : object 'x' not found
I know that I could change the line
lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))
a
lowerfunction(substitute(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3])))
in topfunction , but in my real application, the topfunction is created by the user, so the solution should happen somehow at the lowerfunction level or even at the myfun level. But since they have already lost information about x , I do not know if this can be done?
In a real application, topfunction builds a model using lowerfunction and calculates its likelihood, while the lowerfunction argument is a formula that can contain function calls that will be evaluated using eval . These functions are defined only within the lowerfunction . In addition, lowerfunction can also be called directly, i.e.
x<-1:3 lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3])) # or lowerfunction(myfun(first=x1,second=2)
Therefore, solutions that add x to the lowerfunction argument list are not applicable at all.
Thus, the problem is that eval must take the definition of myfun from one environment (the package namespace or in this case from the lowerfunction environment) and evaluate the arguments of myfun in another environment i.e. in a topfunction environment.