[R] `eval' and environment question
Gabor Grothendieck
ggrothendieck at gmail.com
Tue Nov 13 16:19:45 CET 2007
I think you are looking for eval(quote(x), ...) or evalq(x, ...) .
Those do what you expect. The code you show evaluates
x before eval even gets a chance to deal with it.
On Nov 13, 2007 9:48 AM, Joerg van den Hoff <j.van_den_hoff at fzd.de> wrote:
>
> 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.
> >
>
> ______________________________________________
> 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