首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >rlang::sym在匿名函数中

rlang::sym在匿名函数中
EN

Stack Overflow用户
提问于 2018-08-17 20:26:33
回答 1查看 2.9K关注 0票数 19

我最近注意到,rlang::sym似乎不适用于匿名函数,我也不明白为什么。这里有一个例子,它非常笨拙和丑陋,但我认为它说明了这一点

代码语言:javascript
复制
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和b的不同组合做同样的事情:

代码语言:javascript
复制
d <- tibble(x = c("x1", "x2"),
            y = c("x2", "x1"))
d %>% mutate(tmp = map2(x, y, get_it))

但是,如果我试图对匿名函数执行完全相同的操作,则无法工作:

代码语言:javascript
复制
d %>% mutate(tmp = map2(x, y, function(a, b){
data %>%
    mutate(y1 = !!rlang::sym(a)) %>%
    mutate(y2 = !!rlang::sym(b)) %>%
    select(y1, y2, val)
}))

这在object 'a' not found中失败了,尽管函数完全相同,只是在这里它是匿名的。有人能解释原因吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-18 06:47:03

问题不是匿名函数,而是!!的操作符优先级。!!的帮助页面声明:

那个!操作符取消引用它的参数。它将立即在周围的上下文中得到值。

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

在您的示例中,!!取消引用是针对外部mutate()执行的,然后尝试在d中查找列x1,而不是data。有两种可能的解决办法:

1)将涉及!!的表达式拉到独立函数中(正如您在问题中所做的那样):

代码语言:javascript
复制
res1 <- d %>% mutate(tmp = map2(x, y, get_it))

2)将!!替换为eval,以延迟表达式评估:

代码语言:javascript
复制
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
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51902438

复制
相关文章

相似问题

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