[R] `eval' and environment question
Joerg van den Hoff
j.van_den_hoff at fzd.de
Tue Nov 13 15:48:57 CET 2007
On Tue, Nov 13, 2007 at 09:04:25AM -0500, Duncan Murdoch wrote:
> 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.
OK, I see (and it's probably all in the documentation
somewhere). it's obvious once it's explained. but why _does_
the following work?
#--------------------------------------------
f <- function () {
x <- 1
curenv <- environment()
cat(" eval(x)\n")
r1 = eval(x)
str(r1)
cat(" eval(x, envir = curenv\n")
r2 = eval(x, envir = curenv)
str(r2)
cat(" eval(x, envir = parent.frame())\n")
r3 = eval(x, envir = parent.frame())
str(r3)
#--------------------------------------------
now, the third eval _yields_ a result, although according to
your explanation `x' should be searched for in the global
env. (as was actually the case in my initial example). what
am I missing this time? is `x' copied into the call as a
constant and no longer searched at all or something like
that?
}
>
> 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.
I presume, one could argue for the opposite behaviour as
well? maybe there is some language out there actually doing
it the other way (passing the unevaluated argument string
and leaving everything to the called function)? I will try
to remember this "detail" and then it's fine with me, but
from the outset it's quite irritating that writing down a
call which is identical to the definition of the function
(including its defaults) does not necessarily yield the same
result as when the defaults are really used.
>
> 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.
hope you're not meaning me...
thanks
joerg
>
> 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