rlang:错误:无法将函数转换为字符串

时间:2019-08-14 18:14:27

标签: r rlang tidyeval

我创建了一个函数以将函数名称转换为字符串。版本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,它会在函数内部求值,从而引发错误消息。但是为什么会这样,因为我没有做任何作业?

我的问题是为什么会发生这种情况,还有更好的方法将函数名称转换为字符串吗?

感谢您的帮助,谢谢!

3 个答案:

答案 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()

强制对x进行求值
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()

来源:

  

http://adv-r.had.co.nz/Functions.html