[R] Problems with eval() in connection with match.call()
Duncan Murdoch
murdoch at stats.uwo.ca
Tue Jul 5 02:37:41 CEST 2005
Søren Højsgaard wrote:
> Dear all, I have a problem when passing parms from one function to another when the argument list is just '...'. Consider this example:
>
> foo<-function(){
> xx <- 111222
> bar(x=xx)
> }
> bar <- function(...){
> cl <- match.call(expand.dots=TRUE)
> print(cl)
> x <- eval(cl$x)
> print(x)
> }
> foo()
>
>
>>bar(x = xx)
>>Error in eval(expr, envir, enclos) : Object "xx" not found
>
>
> My expectation was, that xx would be evaluated to 111222 in foo before being passed on to bar, but obviously it is not so. Should I do something explicitely in foo() to 'evaluate' xx or need I do something special in bar()??
Hi Søren.
You need to use eval.parent(cl$x) (which is the same as eval(cl$x,
envir=parent.frame())) to get what you want. You want the evaluation to
happen in the caller's frame of reference, not in bar's frame.
Generally when you eval() an expression, evaluation takes place in the
current frame: the function's local frame when it's in a function, the
global frame when you do it at a command line. You can use the envir=
argument to change where it takes place.
Things look different when you have named parameters, e.g.
bar <- function(x) {
print(x)
}
because in this case, the argument gets turned into a "promise" at the
time of the call, and a promise knows its own evaluation frame. There's
nothing really special about named parameters though, e.g.
> bar <- function(...) {
+ cl <- list(...)
+ print(cl$x)
+ }
> foo()
[1] 111222
By using match.call, you ignore the environment, and only see the
expression.
I imagine you could put together an example where eval.parent() gets the
evaluation wrong, e.g. because you want to evaluate in the parent's
parent. I was a little surprised that it didn't happen here:
> foo
function(){
xx <- 111222
bar2(x=xx)
}
> bar2
function(...) { bar(...) }
> bar
function(...){
cl <- match.call(expand.dots=TRUE)
print(cl)
x <- eval.parent(cl$x)
print(x)
}
> foo()
bar(x = ..1)
[1] 111222
I guess match.call() works hard to be helpful.
Duncan Murdoch
More information about the R-help
mailing list