Reputation: 8806
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
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