【问题标题】:rlang: using function argument in default assignment functionrlang:在默认赋值函数中使用函数参数
【发布时间】:2019-08-14 19:34:34
【问题描述】:

使用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(作为对用户可用功能的额外提示)。

【问题讨论】:

    标签: r rlang


    【解决方案1】:

    这应该可以工作

    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 能够看到原始符号。

    【讨论】:

    • 这行得通,谢谢;你能解释一下为什么quote-unquote步骤是必要的吗?该错误表明它确实找到了正确的符号 - 那么问题是什么?
    • 没有quote/unquote你基本上只是调用test.helper(z, df)所以当你运行enquo(z)你会看到表达式z然后你运行eval_tidy,必须评估来自父环境的z。因此,您将y 捕获为一个quosure,您正在捕获z(它指向y,但不一样)。
    猜你喜欢
    • 2017-07-12
    • 2016-10-30
    • 2017-02-07
    • 2012-02-28
    • 1970-01-01
    • 2011-02-20
    • 2011-04-09
    • 2019-09-11
    相关资源
    最近更新 更多