传递未计算的表达式来替换+评估组合

问题描述 投票:0回答:1

我正在尝试传递一个应该根据数据框进行评估的表达式,本质上是镜像

subset()
。问题是,我需要能够将它放在其他函数中。

这本质上意味着保留表达式并且在合适的时间之前不对其进行求值(即调用类似子集的函数)。

我最终成功的方法是传递

env
和默认值
sys.frame(sys.nframe())
,它应该评估函数的框架。缺点是这需要作为每个外部函数的参数以保留嵌套属性:

f1 = function(x, expr, env=sys.frame(sys.nframe())){
    expr = substitute(expr, env)
    eval(expr, x)
    }

f2 = function(x, expr, env=sys.frame(sys.nframe())){
    f1(x, expr, env)
    }

f3 = function(x, expr, env=sys.frame(sys.nframe())){
    f2(x, expr, env)
    }

f4 = function(x, expr){
    f2(x, expr) # no env passing
    }

m = head(mtcars, 2) # less typing

f1(m, mpg > 20) # TRUE TRUE -- expected
f2(m, mpg > 20) # TRUE TRUE -- yaay
f3(m, mpg > 20) # TRUE TRUE -- yaay
f4(m, mpg > 20) # expr      -- naay :(

我可以重写

f1
以便它自动展开调用堆栈并找到正确的
env
来替换传递的表达式吗?

r substitution
1个回答
0
投票

您可以使用

do.call()
建立通话。例如

f1 = function(x, expr){
  expr = substitute(expr)
  eval(expr, x)
}

f2 = function(x, expr){
  do.call("f1", list(x, substitute(expr)))
}

f3 = function(x, expr){
  do.call("f2", list(x, substitute(expr)))
}
f1(m, mpg > 20) 
# [1] TRUE TRUE
f2(m, mpg > 20) 
# [1] TRUE TRUE
f3(m, mpg > 20) 
# [1] TRUE TRUE

但总的来说,我强烈建议不要这样做。通常,您将有一个面向用户的函数来处理非标准评估,然后您只需传递一个带引号的语言字符串,或者在 rlang/tidyverse 世界中,传递一个您可以稍后评估的 quosure。当尝试以编程方式使用函数时,依赖嵌套的非标准评估调用通常只会导致更多麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.