如何使用rlang::call2()获取R包命名空间中的变量而非函数
如何通过rlang::call2()获取其他R包的非函数导出变量?
报错原因
你之前的写法报错是因为rlang::call2()的核心作用是构造函数调用表达式,你把变量名传入.fn参数时,生成的表达式会尝试将该变量作为函数执行,遇到非函数类型的变量自然会抛出「attempt to apply non-function」错误。
解决方案
你可以通过call2()调用base包的get()或getExportedValue()函数来间接提取目标包的导出变量,这两个函数都是R自带的基础函数,不需要额外依赖,且全程不会触发你的包对目标包的显式依赖声明要求。
方法1:使用get()函数
通用写法如下:
# 构造获取变量的调用 call <- rlang::call2( .fn = "get", x = "a", # 目标变量名 envir = asNamespace("foo") # 目标包的命名空间 ) result <- base::eval(call)
对应phyloseq的实际场景代码:
call <- rlang::call2( .fn = "get", x = "distanceMethodList", envir = asNamespace("phyloseq") ) result <- base::eval(call)
方法2:使用getExportedValue()函数(更稳妥,专门针对包导出变量)
这个函数是base包专门用来提取包命名空间中导出变量的工具,不需要手动转换命名空间,写法更简洁:
# 通用写法 call <- rlang::call2( .fn = "getExportedValue", ns = "foo", # 目标包名 name = "a" # 目标变量名 ) result <- base::eval(call) # phyloseq实际示例 call <- rlang::call2( .fn = "getExportedValue", ns = "phyloseq", name = "distanceMethodList" ) result <- base::eval(call)
注意事项
- 该方案和你之前用
call2()调用其他包函数的逻辑完全一致,只会在运行时检测目标包是否安装,不会要求你在包的DESCRIPTION文件中添加目标包为显式依赖,不会增加依赖体积。 - 如果目标变量是包的非导出内部变量,可以把
get()的inherits参数设为TRUE即可提取。
内容的提问来源于stack exchange,提问作者cmo
相关产品推荐
相关产品推荐

