[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