R中如何获取传递给重载泛型函数的原始表达式?
原因
plot是R的泛型函数,它的调用逻辑和普通函数plot2存在本质区别:
- 调用
plot2(variable_name)时,作为普通函数,enexpr(x)直接捕获了传入的未求值表达式variable_name,因此能输出预期结果。 - 而调用
plot(variable_name)时,R会先对variable_name求值,得到带s类属性的数值1,再根据这个求值后的对象的类来调度plot.s方法。此时plot.s接收的x已经是求值后的对象,自然无法获取原始的变量名表达式。
简言之,泛型函数的方法调度发生在参数求值之后,这是导致问题的核心原因。
解决方法
要在泛型方法中获取原始表达式,需要在泛型函数的调度流程早期捕获未求值的表达式,具体有几种实现方式:
方式1:自定义泛型函数
如果可以替换默认的plot泛型,重新定义一个支持捕获表达式的泛型:
library(rlang) make_s = function(x) structure(x, class = "s") # 重定义plot泛型,先捕获未求值表达式再调度 plot <- function(x, ...) { expr <- enexpr(x) UseMethod("plot") } # 为s类实现方法,直接获取捕获的表达式 plot.s = function(x, ...) { expr <- enexpr(x) print(expr) } variable_name = make_s(1) plot(variable_name) # 输出: variable_name
方式2:从调用栈提取原始表达式
如果不想修改默认泛型,可以通过调用栈工具从上层环境中提取原始表达式:
library(rlang) make_s = function(x) structure(x, class = "s") plot.s = function(x) { # 从父调用环境中提取x的原始表达式 expr <- substitute(x, envir = parent.frame()) print(expr) } variable_name = make_s(1) plot(variable_name) # 输出: variable_name
方式3:使用rlang的引用语法
借助rlang的引用工具,从父环境中捕获未求值的表达式:
library(rlang) make_s = function(x) structure(x, class = "s") plot.s = function(x) { # 捕获x的引用并提取表达式 quo <- enquo(x) print(get_expr(quo)) } variable_name = make_s(1) plot(variable_name) # 输出: variable_name
内容的提问来源于stack exchange,提问作者algebruh
相关产品推荐
相关产品推荐

