[R] Understanding eval
Charilaos Skiadas
cskiadas at gmail.com
Mon Dec 24 04:30:16 CET 2007
On Dec 23, 2007, at 9:21 AM, Duncan Murdoch wrote:
> 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.
It was clear enough ;). I need to learn to use bquote more often ....
Thanks,
Haris Skiadas
Department of Mathematics and Computer Science
Hanover College
> 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
>>>
More information about the R-help
mailing list