[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