Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
匿名函数中的rlang::sym_R_Rlang_Nse_Tidyeval - Fatal编程技术网

匿名函数中的rlang::sym

匿名函数中的rlang::sym,r,rlang,nse,tidyeval,R,Rlang,Nse,Tidyeval,我最近注意到,rlang::sym在匿名函数中似乎不起作用,我不明白为什么。这里有一个例子,它相当笨拙和丑陋,但我认为它说明了这一点 require(tidyverse) data <- tibble(x1 = letters[1:3], x2 = letters[4:6], val = 1:3) get_it <- function(a, b){ data %>% mutate(y1 = !

我最近注意到,
rlang::sym
在匿名函数中似乎不起作用,我不明白为什么。这里有一个例子,它相当笨拙和丑陋,但我认为它说明了这一点

require(tidyverse)
data <- tibble(x1 = letters[1:3],
               x2 = letters[4:6],
               val = 1:3)

get_it <- function(a, b){
    data %>%
        mutate(y1 = !!rlang::sym(a)) %>%
        mutate(y2 = !!rlang::sym(b)) %>%
        select(y1, y2, val)
}
get_it("x1", "x2")

如果未找到
对象“a”,则此操作失败
,即使函数完全相同,只是这里的函数是匿名的。有人能解释为什么吗?

问题不是匿名函数,而是
的运算符优先级
的帮助页声明

这个!!运算符取消引用其参数。它在周围环境中立即得到评估

这意味着,当您编写复杂的NSE表达式时,例如
select
inside
mutate
,将在整个表达式的环境中进行取消引用。正如@lionel所指出的,取消引号优先于其他事情,比如创建匿名函数环境

在您的情况下,
取消引用是针对外部
mutate()
,然后尝试在
d
中查找列
x1
,而不是
数据。有两种可能的解决方案:

1) 拉动包含
的表达式编码为独立函数(如您在问题中所做的):


嗯,真是个难题。我认为这一定与定义了函数的环境有关,但还不能消除差异……这可能不是一个bug,但我会在Git上报告它是一个问题。如果我们消除了rlang,它在这里实际上并不需要,那么它就可以工作:
function(a,b)data%>%mutate(y1=.[a]],y2=.[b]])%>%select(y1,y2,val)
因此,匿名函数似乎可以工作,但不能在其中使用rlang。取消引用不是函数调用:它总是在最开始、最外层的引用函数时生效。这就是为什么在使用匿名函数时必须稍微小心的原因。当匿名函数表示稍后创建的作用域时,取消引用会立即发生,因此存在时间问题。这是我们决定反对
UQ()
UQS()的原因之一
尽管语义非常不同,但看起来太像函数调用。这是一个很好的答案,但问题不在于嵌套的变异。这是一个匿名函数中的反引号,正如您用
显示的那样!!我
举个例子。虽然我想嵌套变异可能会造成类似的时间问题。谢谢你的澄清,@lionel。从开发者那里听到消息总是很棒的。我之所以认为这是一个嵌套问题,是因为我的上一个示例有
在匿名函数中,工作正常。但你是对的;它归结为NSE表达式中的运算符优先级,而不是嵌套。我修改了答案中的语言,使之更加精确。(顺便说一句,你的
rlang
软件包的忠实粉丝!)根据你的回答,你可以使用
eval
eval\u-tidy
而不是
解决了优先级问题,尤其是在嵌套
mutate
s的上下文中出现的优先级问题。@TimTeaFan:Done。谢谢你的建议。
d <- tibble(x = c("x1", "x2"),
            y = c("x2", "x1"))
d %>% mutate(tmp = map2(x, y, get_it))
d %>% mutate(tmp = map2(x, y, function(a, b){
data %>%
    mutate(y1 = !!rlang::sym(a)) %>%
    mutate(y2 = !!rlang::sym(b)) %>%
    select(y1, y2, val)
}))
res1 <- d %>% mutate(tmp = map2(x, y, get_it))
res2 <- d %>% mutate(tmp = map2(x, y, function(a, b){
  data %>%
    mutate(y1 = eval(rlang::sym(a))) %>%
    mutate(y2 = eval(rlang::sym(b))) %>%
    select(y1, y2, val)
}))

identical(res1, res2)       #TRUE