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.