[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