使用 `!!` 而不附加 `rlang`

dol*_*071 2 r ggplot2 r-package rlang

我正在编写一个包,我的一个函数生成一个 ggplot。我只想导入 ggplot2 或 rlang (不依赖它们)。经过一番尝试和错误后,我设法让它工作,但现在我不确定它为什么工作。

所以我的问题是,为什么下面的代码可以在不直接访问的情况!!下工作::

arg1 <- "Species"
ggplot2::ggplot(iris, ggplot2::aes(x = Petal.Width, y = !!rlang::sym(arg1))) + 
    ggplot2::geom_bar(stat = "summary", fun = "max")
Run Code Online (Sandbox Code Playgroud)

我的理解是,为了访问该!!函数,我应该使用 指定包::,但这个示例有效,所以我缺少什么?

Kon*_*lph 7

它之所以有效,是因为 \xe2\x80\x98rlang\xe2\x80\x99/tidy 评估并没有 \xe2\x80\x99t 实际上解析了该!!运算符,它甚至没有定义这样一个运算符\xc2\xa0\xe2\ x80\x94\xc2\xa0 实际上这个运算符根本不存在\xe2\x80\x99!它\xe2\x80\x99 只是两个链式!运算符,它们永远不会被评估,因为整洁的评估使用非标准评估。\xe2\x80\x98rlang\xe2\x80\x99 中的实际实现是用 C++ 编写的,它\xe2\x80\x99s 相当复杂地修复了 R\xe2\x80\x99s 运算符优先级规则中的不匹配,但它是一个简化版本功能的子集可能如下所示:

\n
bang = as.name(\'!\')\n\ninterpolate_bang_bang = function (expr, envir) {\n    if (is.call(expr) && expr[[1L]] == bang) {\n        if (is.call(expr[[2L]]) && expr[[2L]][[1L]] == bang) {\n            eval(expr[[2L]][[2L]], envir = envir)\n        } else {\n            expr\n        }\n    } else {\n        expr\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这测试未计算的表达式是否完全是!! \xe2\x80\xb9something\xe2\x80\xba,并将其替换为 的计算版本\xe2\x80\xb9something\xe2\x80\xba。真正的实现更加复杂,因为它需要处理任意复杂的嵌套表达式(例如1 + !!x),并且它还执行许多其他操作。但基本事实如上所示:没有\xe2\x80\x99s!!运算符。相反,\xe2\x80\x98rlang\xe2\x80\x99 检查未计算的表达式是否包含两个立即嵌套的运算符调用!

\n

因此,即使您愿意,也无法\xe2\x80\x99t 导入或附加!!运算符。

\n

  • 一些额外的澄清会有所帮助。将两个“!”运算符链接在一起会产生逻辑...例如“!!TRUE”返回“TRUE”。它的功能类似于 NSE 中的转义字符吗? (3认同)
  • @IRTFM我在康拉德链接的同一手册的[19.4.6](https://adv-r.hadley.nz/quasiquotation.html#the-polite-fiction-of)部分找到了更好的解释。但这里的手册仍然难以捉摸。 (3认同)