[R] `eval' and environment question

Duncan Murdoch murdoch at stats.uwo.ca
Tue Nov 13 15:04:25 CET 2007


On 11/13/2007 8:39 AM, Joerg van den Hoff wrote:
> my   understanding   of   `eval'   behaviour   is  obviously
> incomplete.
> 
> my    question:   usually   `eval(expr)'   and   `eval(expr,
> envir=parent.frame())' should be identical.   why  does  the
> last  `eval'  (yielding `r3') in this code _not_ evaluate in
> the local environment of function  `f'  but  rather  in  the
> global environment (if `f' is called from there)?]

Because you said "parent.frame()" as its value.  The values of 
explicitly passed arguments are evaluated in the frame of the caller, 
i.e. in the evaluation frame of f().  There, parent.frame() is the frame 
that called f(), i.e. the global environment.

Default values for parameters are evaluated in the evaluation frame of 
the function using them.  So if you don't specify envir in a call to 
eval(), parent.frame() is evaluated in the eval evaluation frame, and it 
refers to whatever function called eval().

> 
> #----------------------------------------------------------
> f <- function () {
> 
>    a <- 1
>    x <- 1
> 
>    model        <- y ~ a * x
>    fitfunc      <- deriv(model[[3]], c("a"), c("a", "x"))
>    call.fitfunc <- c(list(fitfunc), as.name("a"), as.name("x"))
>    call.fitfunc <- as.call(call.fitfunc)
> 
>    curenv <- environment()
> 
>    cat(" eval(call.fitfunc)\n")
>    r1 = eval(call.fitfunc)
>    str(r1)
> 
>    cat(" eval(call.fitfunc, envir = curenv)\n")
>    r2 = eval(call.fitfunc, envir = curenv)
>    str(r2)
> 
>    cat(" eval(call.fitfunc, envir = parent.frame())\n")
>    r3 = eval(call.fitfunc, envir = parent.frame())
>    str(r3)
> 
> }
> #----------------------------------------------------------
> 
> 
> `args(eval)' yields:
> 
> "function (expr, envir = parent.frame(), enclos = if (is.list(envir) || 
>     is.pairlist(envir)) parent.frame() else baseenv())"
> 
> 
> and  the manpage says the same: the default value of `envir'
> is `parent.frame()'. so I  would  expect  (lazy  evaluation)
> that  providing  the  default argument explicitely should'nt
> alter the behaviour. where is my error?

Lazy evaluation affects the order of evaluation, but not the evaluation 
environment.  If you pass an argument to a function, it will be 
evaluated in your environment.  If you rely on the function to provide a 
default, that will be evaluated in the environment of the function.

It all makes sense:  when you write the function you've got no idea what 
the caller will be like, so you can't refer to its environment in your 
defaults.  On the other hand, when you call a function you shouldn't 
care what its internal environment looks like, so your arguments should 
be evaluatable in your own environment, and their value shouldn't change 
just because the implementation of the function changes.

This all gets more complicated with formulas in functions like nls(). 
Formulas normally have an environment attached to them too, but 
sometimes people mess with it, and then things can go crazy.

Duncan Murdoch
> 
> regards,
> 
> joerg
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list