You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R包内使用devtools::load_all()时工厂函数输出赋值失败求助

编辑 - 临时可行方案

我在回复中写了一个较为笨拙的解决方案,但不确定这是否是实现这类常见需求的正确方式。


问题背景

我编写的函数都遵循同一模板:给定若干内部函数及其部分参数,一个「外层函数」对这些内部函数进行求和与乘积运算。外层函数的组合方式是预先设定的,但用户需要能自由设置内部函数的参数。由于无法预知具体函数及参数,创建一次性包装函数不可行。

为了代码的维护与优化,我认为创建一个「工厂函数」来生成所需的外层函数是合理的。该工厂函数既能帮助我为包创建其他实用函数,也允许用户生成同类型的自定义函数。我参考相关资料实现了该工厂函数,在常规R会话中加载并运行该工厂函数,将其输出赋值给变量后,生成的函数完全符合预期。

但在R包内使用devtools::load_all()执行相同的赋值操作时,却无法正常工作。

我进行了排查与实验,缩小了问题范围,相关实验及结果已放在公开仓库中。这是我首次接触函数组件、环境等正式概念,可能术语或理解存在偏差。下方是我整理的最小复现代码。

基础排查

我认为这并非devtools或包配置问题。我查阅了一些旧帖与博客,包括相关讨论和文档。

实验内容
  • geom_shifted.R中的dgeom_shifted_manual():为已知函数及参数创建包装函数无问题,这是一个展示部分预期行为的硬编码示例。
  • geom_shifted.R中的dgeom_shifted_programmatic():该函数实现了我需要的行为。给定一个函数(后续会扩展到多个函数)及部分参数的转换规则,工厂函数shift_support()会输出我需要的外层函数。在交互R会话中,该函数完全符合预期:若注释掉它的创建代码,运行load_all()后再取消注释并执行创建,可得到预期结果;但如果不注释直接运行load_all(),会报错:

Error in load_all():
Failed to load R/geom_shifted.R
Caused by error in shift_support():
could not find function "shift_support"
Run rlang::last_trace() to see where the error occurred.
此时R无法找到该工厂函数。

  • geom_shifted.R中的util_caller2():该示例表明,若将工具函数(即使未导出到namespace)包装在另一个函数内,可正常工作。
  • geom_shifted.R中的util_caller3:直接将geom_shifted.R中的对象赋值为support_utils.R中定义的函数的输出,会出现相同的"could not find function"错误。
  • geom_shifted.R中的stats_util_caller1:(同上)
  • geom_shifted.R中的stats_util_caller2:即使工厂/工具函数与赋值代码在同一文件中,仍会出现相同问题。
  • geom_shifted.R中的uses_stats_util_caller2:表明创建一个伪包装函数可避免报错,但无法真正解决问题。
结论

总体来看,这似乎不是命名空间问题。我认为可通过修改工厂函数的调用环境来解决问题——这也是伪包装函数能避免报错的原因。但我对环境与包的相关知识不足,无法实现无额外操作的正常运行(无需创建单独的utils配套包)。

我还觉得,即便能按上述方式解决,这可能也不是规范的实现方式。我的需求在函数式编程中应该很常见,但我尚未找到针对R包场景的相关资料。从更宏观的角度看,是否存在更深层次的设计问题?我的思路是否有误?

非常感谢!

最小复现代码

创建一个新包,在源文件中粘贴以下代码:

uses_stats_util_caller2 <- function() {
  stats_util_in_same_file(stats::dgeom)
}

### 取消注释并运行load_all()会报错:"...could not find function..."
### 这只是权宜之计,并未真正解决问题
# uses_uses_stats_util_caller2 <- uses_stats_util_caller2()

stats_util_in_same_file <- function(distribution_function) {
  return(distribution_function)
}
  • 在终端运行load_all(),此时不会报错但也无实际功能。
  • 接着在终端执行赋值语句uses_uses_stats_util_caller2 <- uses_stats_util_caller2(),可得到预期结果。
  • 现在取消注释上述赋值代码块,重新运行load_all(),会出现报错。
  • 若将stats_util_in_same_file()放在单独的源文件并导出(更贴近真实场景),结果一致。

内容的提问来源于stack exchange,提问作者user23471877

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 08:04:52