如何调用运行时获取名称的开发中R包的指定函数
解决方案
这个问题其实挺常见的——当你只能动态获取包名、没法硬编码包名::函数名的时候,直接把拼接好的字符串传给get()确实行不通,因为get()只会查找单一的对象名,而不是带命名空间的表达式。下面有几个实用的方法可以解决你的问题:
方法1:利用命名空间环境获取函数
既然你已经通过desc拿到了包名,你可以先通过asNamespace()获取该包的命名空间环境,再用get()在这个环境里查找目标函数:
# 先获取包名 library(desc) desc <- description$new("src") pkg_name <- desc$get("Package") # 获取目标函数 target_fn <- get("do_a_thing", envir = asNamespace(pkg_name), mode = "function") # 调用函数(如果有参数直接加在括号里即可) target_fn()
这个方法逻辑清晰,直接操作包的命名空间,不需要额外依赖其他工具包。
方法2:解析并求值表达式
如果你习惯用tidyverse风格的工具,可以用rlang包的函数把拼接好的函数名字符串转换成表达式,再执行求值:
library(rlang) library(desc) desc <- description$new("src") pkg_name <- desc$get("Package") # 拼接成带命名空间的函数字符串,转成可执行表达式 fn_expr <- parse_expr(paste(pkg_name, "::do_a_thing", sep = "")) # 执行表达式 eval_tidy(fn_expr)
这个方法灵活性更高,如果你需要动态生成带参数的复杂调用,只需要修改拼接的字符串再解析即可。
方法3:使用getExportedValue()(推荐用于导出函数)
如果你确定do_a_thing是包对外暴露的导出函数(也就是用户可以直接调用的函数),可以用getExportedValue()来获取,这个方法会确保只获取包公开的函数,安全性更高:
library(desc) desc <- description$new("src") pkg_name <- desc$get("Package") # 获取导出的目标函数 target_fn <- getExportedValue(pkg_name, "do_a_thing") # 调用函数,有参数的话用do.call更方便 do.call(target_fn, args = list()) # 把参数放在list里,比如list(arg1 = 1, arg2 = "test")
为什么你的原方法不行?
你之前尝试用get("MyWeirdPackageName::do_a_thing")失败,是因为get()的第一个参数需要的是单一对象的名称字符串,而包名::函数名是一个R表达式,不是单一的对象名,所以get()找不到对应的对象。上面的方法都是绕开这个限制,直接从命名空间获取或者解析表达式来执行调用。
内容的提问来源于stack exchange,提问作者dingus
相关产品推荐
相关产品推荐

