如何让ensym实现二次求值?R语言对象名称推断问题
解决R中ensym跨函数获取原始对象名称的问题
问题出在函数调用的层级上:当你把starwars传给test_fun的test_data参数后,在test_fun内部调用get_obj_name(test_data)时,传给get_obj_name的是当前函数里的test_data这个参数符号,ensym只能捕获当前函数作用域内的符号名称,所以返回的是test_data而非原始的starwars。
这里提供两种可行的解决办法:
方法一:让工具函数从调用环境中获取符号
修改get_obj_name,让它去上层调用环境中解析表达式,这样就能拿到原始的对象名称:
starwars = dplyr::starwars get_obj_name <- function(obj_expr, env = rlang::caller_env()) { var = rlang::enexpr(obj_expr) print(as.character(var)) } test_fun <- function(test_data, hej = NULL) { if (is.null(hej)) { get_obj_name(test_data) } } test_fun(starwars) # 输出 "starwars"
方法二:在主函数中先捕获符号再传递
先在test_fun里用ensym捕获原始符号,再把这个符号传给工具函数:
starwars = dplyr::starwars get_obj_name <- function(var) { print(as.character(var)) } test_fun <- function(test_data, hej = NULL) { if (is.null(hej)) { var = rlang::ensym(test_data) get_obj_name(var) } } test_fun(starwars) # 输出 "starwars"
两种方法的区别:方法一让工具函数自动处理调用环境,主函数不需要额外修改;方法二更灵活,如果你需要在主函数中对符号做额外处理(比如拼接字符串、判断名称合法性),这种方式更合适。
内容的提问来源于stack exchange,提问作者Karl
相关产品推荐
相关产品推荐

