{rlang} 的“卷曲”运算符“{{”是如何实现的?

Blu*_*oxe 2 r metaprogramming nse tidyverse rlang

{rlang}文档help("nse-force")给出了以下内容:

函数参数的卷曲运算符 {{ }} 有点特殊,因为它强制函数参数并立即解除它。解融合的表达式被就地替换,准备在另一个上下文(例如数据帧)中进行计算。

我同样对 'bang-bang' 运算符感到困惑!!,关于它的文档对于幕后发生的事情同样迟钝。

我的问题不是关于如何使用该运算符,因为它的用法(我认为)非常简单。相反,我想知道这样的运算符在{rlang}幕后实际上是如何实现的。根据该包的作者之一的说法,{{ foo }}基本上变成了!!rlang::enquo(foo). 然而,我仍然不知道像这样的非标准运算符实际上是如何实现的,特别是考虑到这个运算符似乎“正常工作”,无论它是否被{rlang}函数使用。实际上它只适用于由 {rlang} 支持的函数 - 感谢@Konrad Rudolph 的更正。

查看源代码,我只能猜测它是用 C 或 C++ 完成的。谁能给我更多信息吗?

Kon*_*lph 7

\n

然而,我仍然不知道像这样的非标准运算符实际上是如何实现的,特别是考虑到这个运算符似乎“正常工作”,无论它是否被 {rlang} 函数使用。

\n
\n

不能\xe2\x80\x99t \xe2\x80\x9c只适用于\xe2\x80\x9d与任意函数\xc2\xa0\xe2\x80\x94\xc2\xa0相反:函数确实需要注意整洁的评估。正如您可能猜到的那样,\xe2\x80\x99s 没有{{运算符。相反,\xe2\x80\x98rlang\xe2\x80\x99 使用 NSE 捕获未计算的参数,然后检查表达式的解析树是否包含两个嵌套{调用。然后它获取未计算的表达式并对其进行适当的转换。

\n

  • @BluVoxe 卷曲“运算符”的实际识别发生在这里:https://github.com/r-lib/rlang/blob/3ba19df8b234ca328dfd703085d2499a6790bd29/src/internal/nse-inject.c#L45-L46;转变为 bang-bang-enquo 发生在这里:https://github.com/r-lib/rlang/blob/3ba19df8b234ca328dfd703085d2499a6790bd29/src/internal/nse-inject.c#L308-L311。但我想强调的是,整个事情可以用纯 R 实现,尽管效率较低。 (3认同)
  • 对于其他人来说,实现该功能的实际拉取请求是[此处](https://github.com/r-lib/rlang/commit/d0901598065afcf41dcb55adb6272aca666b7b26) (2认同)