用于编写函数的rlang运算符的解释

Explanation of rlang operators used to write functions

我最近发布了两个与我尝试编写的函数相关的问题 (, )。我收到了每个有用的答案,这导致了以下两个功能:

second_table <- function(dat, variable1, variable2){
 dat %>% 
  tabyl({{variable1}}, {{variable2}}, show_na = FALSE) %>% 
  adorn_percentages("row") %>% 
  adorn_pct_formatting(digits = 1) %>% 
   adorn_ns() 

 }

second_table2 = function(dat, variable1, variable2){
  variable1 <- sym(variable1)
  
  dat %>% 
    tabyl(!!variable1, {{variable2}}, show_na = FALSE) %>% 
    adorn_percentages("row") %>% 
    adorn_pct_formatting(digits = 1) %>% 
    adorn_ns() 
  
}

这些函数按预期工作,但我以前从未使用过 rlang 包,仍然对 {{}} 运算符和 !! 之间的区别感到困惑。 + sym() 在查看可用文档并编写一些附加函数之后。我不喜欢使用我不完全理解的代码,并且相信我将来会进一步使用这些 rlang 运算符,因此非常感谢对这些运算符之间的区别进行简单的语言解释。

R 有一个称为非标准求值 (NSE) 的特殊功能,其中表达式按原样使用而不是被求值。大多数人在加载包时首先遇到 NSE:

a <- "rlang"

print(a)         # Standard evaluation - the expression a is evaluated to its value
# [1] "rlang"

library(a)       # Non-standard evaluation - the expression a is used as-is
# Error in library(a) : there is no package called ‘a’

rlang 通过提供三个主要函数来捕获未计算的符号和表达式来启用复杂的 NSE:

  • sym("x") 捕获一个符号(即变量名、列名等)。旧版本允许 sym(x),但我认为最新版本 rlang 强制输入为字符串。

  • expr(a + b) 捕获任意表达式

  • quo(a + b) 捕获任意表达式和定义这些表达式的环境。

expressions 和 quosures 之间的区别在于,前者的评估将在直接环境中完成,而后者始终在捕获表达式的环境中进行评估:

f <- function(e) {a <- 2; b <- 3; eval_tidy(e)}
a <- 5; b <- 10

f(expr(a+b))   # Evaluated inside f
# [1] 5

f(quo(a+b))    # Evaluated in the environment where it is captured
# [1] 15

所有三个动词都有 en 等价物:ensymenexprenquo。这些用于捕获从函数内部提供给函数的符号和表达式。当您想要消除函数用户自己使用 sym 等的需要时,这很有用:

f <- function(x) {enexpr(x)}      # Expression captured within a function
f(a+b)

# This has exact equivalence to

f <- function(x) {x}
f(expr(a+b))                      # The user has to do the capture themselves

在所有情况下,运算符 !! 都会计算符号和表达式。将其视为类固醇的 eval(),因为 !! 强制立即评估优先于其他所有内容。除其他事项外,这对于更复杂表达式的迭代构造很有用:

a <- expr(b + 2)
expr(d * !!a)      # a is evaluated immediately
# d * (b + 2)

expr(d * eval(a))  # evaluation of a is delayed
# d * eval(a)

综上所述,{{x}}!!enquo(x)

的 shorthand 表示法