强制评估函数参数以便 "trick" 替代()?
Force-evaluate function argument in order to "trick" substitute()?
假设我有一个来自 R 包的函数,为了方便和更好的代码可读性,我想将其包装在一个闭包中。为简单起见,我们假设函数如下所示:
fun <- function(text) {
as.character(substitute(text))
}
当我从控制台调用该函数时,例如
fun(text = "bar")
返回值是 "bar"
,在我的例子中这是期望的行为。函数按原样编写的原因是万一我调用
fun(text = bar)
输出也是"bar"
。仅供参考。这个功能我明明不是自己写的,只是想用一下
问题: 当我从一个函数中调用 fun
时,例如
fun2 <- function(foo) {
fun(text = foo)
}
fun2(foo = "bar")
无论我在调用 fun2
时分配给 foo
什么,输出总是 "foo"
而不是“bar”。 Ofc 我知道这就是 substitute()
的工作方式,但这使得无法(或者至少非常讨厌?)以编程方式使用函数 fun
.
我的问题:有没有一种方法可以在不重写的情况下实现所需的行为fun
?
提前致谢:)
您可以在 fun2
中构造调用并对其求值:
fun2 <- function(foo) {
eval(call("fun", foo))
}
fun2(foo = "bar")
#> [1] "bar"
这里的问题是,如果您通过 bar
未加引号:
,它现在不再有效
fun2(foo = bar)
#> Error in eval(call("fun", foo)) : object 'bar' not found
所以你需要这样的东西:
fun2 <- function(foo) {
if(exists(as.character(substitute(foo)), parent.frame())) {
eval(call("fun", foo))
} else {
eval(call("fun", as.character(substitute(foo))))
}
}
现在两种方式都有效:
fun2(foo = "bar")
#> [1] "bar"
fun2(foo = bar)
#> [1] "bar"
这里的问题是,如果bar
确实存在,那么它会被解释为bar
的值,所以我们有:
fun2(foo = "bar")
#> [1] "bar"
fun2(foo = bar)
#> [1] "bar"
bar <- 1
fun2(foo = bar)
#> [1] "1"
这可能不是您想要的。
但是,如果您要这样做,调用 fun
可能就不再有意义了。也许最简单的事情是
fun2 <- function(foo) {
as.character(match.call()$foo)
}
fun2("bar")
#> [1] "bar"
fun2(bar)
#> [1] "bar"
bar <- 1
fun2(bar)
#> [1] "bar"
假设我有一个来自 R 包的函数,为了方便和更好的代码可读性,我想将其包装在一个闭包中。为简单起见,我们假设函数如下所示:
fun <- function(text) {
as.character(substitute(text))
}
当我从控制台调用该函数时,例如
fun(text = "bar")
返回值是 "bar"
,在我的例子中这是期望的行为。函数按原样编写的原因是万一我调用
fun(text = bar)
输出也是"bar"
。仅供参考。这个功能我明明不是自己写的,只是想用一下
问题: 当我从一个函数中调用 fun
时,例如
fun2 <- function(foo) {
fun(text = foo)
}
fun2(foo = "bar")
无论我在调用 fun2
时分配给 foo
什么,输出总是 "foo"
而不是“bar”。 Ofc 我知道这就是 substitute()
的工作方式,但这使得无法(或者至少非常讨厌?)以编程方式使用函数 fun
.
我的问题:有没有一种方法可以在不重写的情况下实现所需的行为fun
?
提前致谢:)
您可以在 fun2
中构造调用并对其求值:
fun2 <- function(foo) {
eval(call("fun", foo))
}
fun2(foo = "bar")
#> [1] "bar"
这里的问题是,如果您通过 bar
未加引号:
fun2(foo = bar)
#> Error in eval(call("fun", foo)) : object 'bar' not found
所以你需要这样的东西:
fun2 <- function(foo) {
if(exists(as.character(substitute(foo)), parent.frame())) {
eval(call("fun", foo))
} else {
eval(call("fun", as.character(substitute(foo))))
}
}
现在两种方式都有效:
fun2(foo = "bar")
#> [1] "bar"
fun2(foo = bar)
#> [1] "bar"
这里的问题是,如果bar
确实存在,那么它会被解释为bar
的值,所以我们有:
fun2(foo = "bar")
#> [1] "bar"
fun2(foo = bar)
#> [1] "bar"
bar <- 1
fun2(foo = bar)
#> [1] "1"
这可能不是您想要的。
但是,如果您要这样做,调用 fun
可能就不再有意义了。也许最简单的事情是
fun2 <- function(foo) {
as.character(match.call()$foo)
}
fun2("bar")
#> [1] "bar"
fun2(bar)
#> [1] "bar"
bar <- 1
fun2(bar)
#> [1] "bar"