[R] Understanding eval
Duncan Murdoch
murdoch at stats.uwo.ca
Sun Dec 23 15:21:31 CET 2007
On 23/12/2007 9:15 AM, Duncan Murdoch wrote:
> On 22/12/2007 5:45 PM, Charilaos Skiadas wrote:
>> On Dec 22, 2007, at 4:44 PM, Duncan Murdoch wrote:
>>>> 5) eval then creates the environment where this evaluation will
>>>> take place. It does that by creating an environment containing
>>>> the frame "a=5", and with enclosing environment the parent frame
>>>> of foo, which is bar's environment.
>>>> 6) So, as I understand it, the symbol "er" is going to now be
>>>> evaluated in an environment where a is set to 5 and er is set to
>>>> a, along with whatever is in the user's workspace.
>>> I think this part is wrong. A better description is:
>>>
>>> er is going to be evaluated in an environment where a is set to 5.
>>> The parent of that environment is the bar evaluation frame, where
>>> er is set to be a promise to evaluate a in the global environment.
>>>
>>>> 7) So the first step now is looking up a definition for er.
>>>> Nothing is found in the current frame, so the evaluation proceeds
>>>> to bar's environment, where the association "er=a" is found, so
>>>> er is replaced by a.
>>> No, at this point an attempt is made to force the promise.
>>> Promises have their own associated environments, and that's where
>>> the evaluation takes place. In the case of the er object, the
>>> associated environment is the one where bar(a) was called, i.e. the
>>> global environment.
>>>
>>>> 8) Now, and perhaps this is where I misunderstand things, the
>>>> lookup for a will take place. My thinking was that the lookup
>>>> would start from the evaluation environment that eval created,
>>>> and hence would locate the a=5 value. But this is clearly not
>>>> what happens.
>>>> Anyway, hope someone will correct me where I'm wrong, and explain
>>>> to me what I am doing wrong, and ideally how to diagnose such
>>>> things.
>>> Diagnosing things like this is hard. Promises are very difficult
>>> things to look at: as soon as you try to do anything with them
>>> they get evaluated, and there's no way in R code to display them
>>> without that.
>>> You can use substitute() to extract the expression part, but
>>> there's no way to extract the environment part. Maybe there should
>>> be, but it's tricky to get the semantics right. If the function
>>> environment() worked to extract the environment of a promise, then
>>> all sorts of code would fail where I really wanted to evaluate the
>>> arg before extracting the environment.
>> Thank you Duncan, for the very clear explanation.
>>
>> Ok, so the substitute "breaks through" the promise of expr, returning
>> as a language object the promise of er, and there's no easy way to
>> break through that. I ended up with the following, somewhat uglier
>> than I wanted, code, which seems to do what I need in this case, and
>> hopefully will still work in the more general case I want it to. The
>> idea was to break through the er promise in bar, before sending it
>> over to foo. Then foo receives simply an expression, which it can
>> then evaluate. Though I seem to have had to work a bit harder on that
>> part than I expected to. Perhaps there's an easier way? Or things
>> that can go seriously wrong with this way?
>>
>> foo <- function(fr, expr) {
>> ..obj <- list(.=fr)
>> ..expr <- substitute(expr)
>> ..txt <- parse( text=paste("substitute(",..expr,")") )
>
> I think you want
>
> ..txt <- parse( text=paste("substitute(",deparse(..expr),")") )
>
> here, but it's even better not to go through the deparse-parse cycle:
>
> ..txt <- bquote( substitute( .(..expr) ) )
>
> The main thing that could go wrong ...
Sorry, this wasn't written clearly: This was a response to your second
question, not a continuation of the bquote() suggestion.
Duncan Murdoch
is the evaluation of er might not be
> right. Just because it is an argument to bar doesn't mean bar's frame
> or parent.frame() is the right place to evaluate it.
>
> To check for errors, I'd introduce like-named variables at lots of
> levels, and then put them into the expression you were evaluating in
> such a way that you can tell which one was found. For example, put
> x <- "foo" into foo(), x <- "bar" into bar(), and x <- "global" into the
> global environment. Then evaluate some expression that prints x and
> make sure you see the right one.
>
> Duncan Murdoch
>
>> ..expr <- eval(..txt, ..obj, parent.frame())
>> ..expr <- eval(..expr, parent.frame())
>> eval(..expr, ..obj)
>> }
>> bar <- function(parent, er, ...) {
>> .fr=parent
>> g <- substitute(er)
>> foo(.fr, g)
>> }
>>
>> > foo(5,.)
>> [1] 5
>> > bar(5,.)
>> [1] 5
>>
>>
>>> Duncan Murdoch
>> Haris Skiadas
>> Department of Mathematics and Computer Science
>> Hanover College
>>
>> ______________________________________________
>> 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