rlang:在默认赋值函数中使用函数参数

rlang: using function argument in default assignment function

使用 rlang,我希望有一个函数既可以在直接调用时工作,也可以在默认情况下作为构造另一个函数参数的一部分传递参数时工作,例如:

refdf = data.frame(x=1:100, y=runif(100,-1,1))

test.helper <- function(z, df) {
  qz <- enquo(z)
  range(eval_tidy(qz, df))
}
test.helper(y, refdf) # works

test.main <- function(z, df, def = test.helper(z, df)) {
  print(def)
}
test.main(y, refdf)
# doesn't work:  Error in eval_tidy(qz, df) : object 'y' not found 

如果相反,我会

refdf = data.frame(x=1:100, y=runif(100,-1,1))

test.helper <- function(z, df) {
  qz <- as_quosure(z)
  range(eval_tidy(qz, df))
}
test.helper(y, refdf)
# doesn't work: Error in is_quosure(x) : object 'y' not found

test.main <- function(z, df, def = test.helper(enquo(z), df)) {
  print(def)
}
test.main(y, refdf)
# now works 

我觉得我遗漏了一些关于什么时候被引用的东西;有没有我可以使用的替代语法来使两者都起作用?我知道我可以定义一个单独的 test.helper_quo 或类似的东西,但我真的很想在签名中使用 test.helper (作为对用户可用功能的额外提示)。

这应该有效

library(rlang)

test.helper <- function(z, df) {
  qz <- enquo(z)
  range(eval_tidy(qz, df))
}
test.helper(y, refdf) # works

test.main <- function(z, df, def = test.helper(!!enquo(z), df)) {
  print(def)
}
test.main(y, refdf) # works

# or with rlang >= 0.4.0
test.main <- function(z, df, def = test.helper({{z}}, df)) {
  print(def)
}
test.main(y, refdf) # works

请注意,在 def 中,我们需要捕获作为 z 传递的 quosure,然后将其扩展到 test.helper 的调用中,因此它是自己的 enquo将能够看到原始符号。