函数内使用rlang与tidyeval的最佳实践及字符串引用对象解法
用tidyeval实现通过字符串名称获取对象内容
问题场景
现有两个tibble对象t1和t2,希望通过它们的字符串名称,在purrr::map调用中获取对象内容:
library(tidyverse) t1 <- tribble( ~name, "foo" ) t2 <- t1
使用基础R的get()可以实现需求:
ls() %>% map(~get(.x))
但尝试的几种tidyeval写法仅返回对象名称,无法获取内容:
# 仅返回字符串名称 ls() %>% map(~{{.x}}) # 返回捕获的表达式,非对象内容 ls() %>% map(~enquo(.x)) # 返回符号对象,未被求值 ls() %>% map(~sym(.x))
原因解析
{{.x}}:用于注入表达式,但.x本身是字符串,注入后仍为字符串,不会解析为对象enquo(.x):捕获当前环境中的变量表达式,这里捕获的是字符串变量.x本身,而非对应的对象sym(.x):仅将字符串转换为符号(对象的名称标识),但符号未被求值,不会返回对象内容
正确的tidyeval实现
tidyeval的核心是处理符号与表达式的求值,需要先将字符串转为符号,再对符号进行求值:
方法1:使用sym() + eval_tidy()
ls() %>% map(~rlang::eval_tidy(sym(.x)))
方法2:使用parse_expr() + eval_tidy()(适用于更复杂的表达式)
ls() %>% map(~rlang::eval_tidy(rlang::parse_expr(.x)))
说明
get()是基础R中直接通过字符串获取对象的方法,而tidyeval的思路是先将字符串转换为可被求值的符号/表达式,再完成求值,这更符合tidyeval处理元编程的逻辑。
内容的提问来源于stack exchange,提问作者tomw
相关产品推荐
相关产品推荐

