我创建了一个函数以将函数名称转换为字符串。版本1 func_to_string1
运作良好,但版本2 func_to_string2
无法运作。
func_to_string1 <- function(fun){
print(rlang::as_string(rlang::enexpr(fun)))
}
func_to_string2 <- function(fun){
is.function(fun)
print(rlang::as_string(rlang::enexpr(fun)))
}
func_to_string1
的工作原理:
> func_to_string1(sum)
[1] "sum"
func_to_string2
不起作用。
> func_to_string2(sum)
Error: Can't convert a primitive function to a string
Call `rlang::last_error()` to see a backtrace
我的猜测是,通过在将fun
转换为字符串之前调用Javascript
,它会在函数内部求值,从而引发错误消息。但是为什么会这样,因为我没有做任何作业?
我的问题是为什么会发生这种情况,还有更好的方法将函数名称转换为字符串吗?
感谢您的帮助,谢谢!
答案 0 :(得分:4)
也许可以改用它?
func_to_string2 <- function(fun){
is.function(fun)
deparse(substitute(fun))
#print(rlang::as_string(rlang::enexpr(fun)))
}
> func_to_string2(sum)
[1] "sum"
答案 1 :(得分:4)
这不是一个完整的答案,但我认为它不适合发表评论。
R具有一种称为通过承诺的机制,
因此,函数的形式参数是仅在使用时才求值的惰性对象(承诺)。
即使您没有执行任何作业,
对is.function
的调用使用了参数,
因此,根据评估结果来“代替”承诺。
尽管如此,我认为这似乎与rlang
*不一致,
特别是考虑到科里的回答,
这意味着即使使用了给定的参数,R仍然可以找到promise对象;
但是,这样做的机制可能不属于R的公共API。
*编辑:请参见注释。
无论如何,您都可以将enexpr
/ enquo
/ ensym
视为base::missing
,
在某种意义上,您应该只将它们与该函数主体中根本没有使用过的参数一起使用。
答案 2 :(得分:1)
这个问题为懒惰评估提出了一个有趣的观点。
R参数是惰性计算的,这意味着直到需要时才对参数进行计算。
这在Advanced R书中具有以下示例,对此有最好的理解,
f <- function(x) {
10
}
f(stop("This is an error!"))
结果为10,这令人惊讶,因为x从未被调用,因此也从未被求值。我们可以使用force()
f <- function(x) {
force(x)
10
}
f(stop("This is an error!"))
此行为符合预期。实际上,我们甚至不需要force()
(尽管明确表示很好)。
f <- function(x) {
x
10
}
f(stop("This is an error!"))
您在这里打电话的情况就是这样。调用sum
时,函数is.function()
最初是一个符号,而没有参数。实际上,即使这样也会失败。
func_to_string2 <- function(fun){
fun
print(rlang::as_string(rlang::ensym(fun)))
}
总的来说,我认为最好在函数的开头使用enexpr()
。
来源: