rlang: Error: Can't convert a function to a string

rlang: Error: Can't convert a function to a string

我创建了一个将函数名转换为字符串的函数。版本 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,它会在函数内部进行计算,因此会抛出错误消息。但是为什么我没有做任何作业会发生这种情况?

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

感谢任何帮助,谢谢!

也许改用这个?

func_to_string2 <- function(fun){
  is.function(fun)
  deparse(substitute(fun)) 
  #print(rlang::as_string(rlang::enexpr(fun)))
}
> func_to_string2(sum)
[1] "sum"

这不是一个完整的答案,但我认为它不适合发表评论。

R 有一种机制叫做 pass-by-promise, 其中函数的形式参数是惰性对象(承诺),只有在使用时才会被评估。 即使你没有执行任何任务, 对 is.function 的调用使用参数, 所以承诺是 "replaced" 通过评估它的结果。

然而,在我看来,这似乎是 rlang* 中的一个不一致之处, 特别是考虑到科里的回答, 这意味着即使在使用给定参数后,R 仍然可以找到 promise 对象; 不过,这样做的机制可能不是 R 的 public API 的一部分。

*编辑:查看评论。

无论如何,您可以像 base::missing 一样对待 enexpr/enquo/ensym, 从某种意义上说,您应该只将它们与您在函数主体中根本没有使用过的参数一起使用。

这个问题提出了惰性求值的一个有趣观点。

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