首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >rlang::enexpr与base::

rlang::enexpr与base::
EN

Stack Overflow用户
提问于 2020-01-23 15:04:08
回答 1查看 523关注 0票数 2

这个问题与发布在这里上的问题有关。

简而言之,我想知道为什么base::substitute rlang::enexpr 在下面有不同的行为。

代码语言:javascript
复制
#works
f1 <- function(x,y){ 
  do.call("methods", list(substitute(x::y)))
}
f1(broom,tidy)
#does not work
#Error: `arg` must be a symbol
f2 <- function(x,y){
  do.call('methods',list(rlang::enexpr(x::y)))
}
f2(broom,tidy)

更长的版本。在高级R书“第19章”中,您可以看到表19.1和表19.2建议enexprsubstitute在函数调用中应该具有相同的目的(我在这里可能错了,并且很乐意解释为什么我错了)。

我决定对此进行测试,并看到在f1中返回结果,但f2返回一个错误。

有趣的是,如果您使用do.call('methods',list(rlang::expr(broom::tidy))),这是可行的。我觉得这很有趣,因为rlang::expr只是简单地调用rlang::enexpr

在上面的问题中,MrFlick将此函数作为纯rlang解决方案发布。

代码语言:javascript
复制
#also works 
#function from MrFlick in the posted link
f3 <- function(x,y){
x <- rlang::ensym(x)
y <- rlang::ensym(y)
rlang::eval_tidy(rlang::quo(methods(`::`(!!x, !!y))))}

f3(broom,tidy) 

这似乎比我预期的要复杂一些。

了解为什么f1f2不是等效的,或者如何使f2enexpr一起工作,这将是有帮助的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-23 15:29:15

rlang::enexpr()base::substitute()在它们的接口上并不完全等价。enexpr()需要一个变量名,它引用函数的一个输入参数,而substitute()可以处理任意表达式。这需要附加的表达式算法--通过使用rlang::expr()包装并使用un报价运算符!! --将enexpr()的结果放入一个更复杂的表达式中:

代码语言:javascript
复制
g  <- function(x) substitute(x+5)
h  <- function(x) rlang::enexpr(x+5)
h2 <- function(x) rlang::expr( !!rlang::enexpr(x) + 5 )

g(a)   # a + 5
h(a)   # Error: `arg` must be a symbol
h2(a)  # a + 5

要使f2工作,需要对每个参数分别应用rlang::enexpr(),然后使用表达式算法组成整个x::y表达式:

代码语言:javascript
复制
f2 <- function(x,y){
   ee <- rlang::expr( `::`(!!rlang::enexpr(x), !!rlang::enexpr(y)) )
   do.call('methods',list(ee))
}
f2(broom,tidy)

请注意,我们必须在前缀表示法中使用::,因为!!::相邻是解析器的一个问题。换句话说,!!a :: !!b类型的表达式会导致解析错误。

另一种方法是让用户自己编写表达式。这样你就可以用一个rlang::enexpr()就可以逃脱了

代码语言:javascript
复制
f3 <- function(x)
  do.call('methods',list(rlang::enexpr(x)))
f3( broom::tidy )

边注:

即使expr()调用enexpr(),该调用也与expr()本身的范围有关。考虑一下,

代码语言:javascript
复制
f1 <- function(x)  rlang::enexpr(x)

f2 <- function(x) {
  g <- function(y) rlang::enexpr(y)
  g(x)
}

这两者不是等价的,因为第二个enexpr()的作用域是内部函数g(),而不是外部f2()

代码语言:javascript
复制
f1(abc)   # abc
f2(abc)   # x
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59881494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档