Heisenberg
Heisenberg

Reputation: 8806

How is the evaluation environment retained after a promise has been turned into a call?

In the following minimal working example, a_promise is turned into a_call using substitute(). I can see that the a_promise object store both the expression and the environment where that expression should be evaluated.

However, as far as I can tell, once it's turned into a_call, the only thing that a_call stores is simply the expression (condition) with no reference to the environment in which that expression can be evaluated and turned into a >= 4.

However, the error at the end indicates that eval(a_call, df, parent.frame() does try to look for object a, meaning that a_call was indeed translated into a >= 4. How?

library(pryr)
f <- function(df, a_promise) {
  print(promise_info(a_promise)) #> shows both the expression and the eval envir
  a_call <- substitute(a_promise)
  print(a_call) #> condition
  eval(a_call, df, parent.frame())
}

g <- function(df, condition) {
  f(df, condition)
}

df <- data.frame(a=1:5, b=5:1)
g(df, a >= 4)
#> Error in eval(expr, envir, enclos) : object 'a' not found 

Upvotes: 0

Views: 124

Answers (1)

MrFlick
MrFlick

Reputation: 206197

When you do

a_call <- substitute(a_promise)

you are getting the expression that was passed to a_promise which is condition. The class of a_call is symbol (not a call or expression). This symbol is really a pointer to another promise in the parent frame that hasn't been resolved yet. So by the time you're at f, you've missed your chance to turn a >= 4 into an expression in the usual substitute way. Now, when you ask for the value of condition you are evaluating the previous promise and getting a non-sensical result. It really comes down to the difference between

eval( a >= 4, df)
# Error in eval(a >= 4, df) : object 'a' not found

and

eval( expression(a >= 4), df)
# [1] FALSE FALSE FALSE  TRUE  TRUE.

When condition is resolving it's promise, it's not doing so inside your eval().

Upvotes: 1

Related Questions