问题
This is borrowed from shiny's function exprToFunction which is used in their reactive function.
Actual question
How can I delay the evaluation of an expression (e.g. specified via arg expr
) in order to "capture" its content when calling a S4 method (as opposed to a standard R function)?
Example
Note that x_1
does not exist yet, that's why we want to delay the evaluation of expr
and just "capture" its content.
Function captureExpression
:
captureExpression <- function(
expr,
caller_offset = 1,
brackets = TRUE
) {
out <- eval(substitute(substitute(expr)), parent.frame(caller_offset))
if (brackets && class(out) != "{") {
out <- substitute({CODE}, list(CODE = out))
}
out
}
captureExpression(x_1 * 2)
# {
# x_1 * 2
# }
Passing unevaluated expr
through works when calling a standard R function:
foo <- function(expr) {
captureExpression(expr = expr)
}
foo(x_1 * 2)
# {
# x_1 * 2
# }
Passing unevaluated expr
through does not work when calling an S4 method:
setGeneric(
name = "bar",
signature = c(
"expr"
),
def = function(
expr,
...
) {
standardGeneric("bar")
}
)
setMethod(
f = "bar",
signature = signature(
expr = "ANY"
),
definition = function(
expr,
...
) {
captureExpression(expr = expr, ...)
})
Applying the S4 method:
bar(x_1 * 2)
# Error in bar(x_1 * 2) :
# error in evaluating the argument 'expr' in selecting a method for function 'bar': Error:
# object 'x_1' not found
bar(x_1 * 2, caller_offset = 2)
# Error in bar(x_1 * 2, caller_offset = 2) :
# error in evaluating the argument 'expr' in selecting a method for function 'bar': Error:
# object 'x_1' not found
bar(x_1 * 2, caller_offset = 3)
# Error in bar(x_1 * 2, caller_offset = 3) :
# error in evaluating the argument 'expr' in selecting a method for function 'bar': Error:
# object 'x_1' not found
I guess this has to do with the way the method dispatch is actually carried out. However, maybe there's a way that this can be done anyways.
来源:https://stackoverflow.com/questions/26462704/non-standard-evaluation-of-expressions-in-s4-context