如何在 R 包中包含闭包?

How to include a closure in an R-package?

我想包含一个闭包,其中包含我们正在编写的 R 包的功能。该函数(及其兄弟函数)将在其环境中包含数据,将输入与数据进行比较,然后 return 结果。为了说明这一点,请考虑一个带有内置电话簿的函数:您查询一个号码,函数 return 是一个名字。

这个函数将被我们的 R 包中的其他几个函数作为助手调用,所以一旦包被加载它就必须存在。我们希望该函数在包环境中可用,就像任何其他函数一样。

我应该通过它在 .onLoad() 中的工厂函数创建它并将它分配给包环境吗?我可以将它作为 .RDS 发送吗?或者 RData,或者这是否违反了 "binary executable code" 上的 CRAN 政策?还是有不同的规范方式?代码和数据(或 RDS/RData)在包目录结构中的什么位置?

(我看到已经讨论了如何 记录 闭包的问题 here)。

为了任何遇到这个问题的人的利益。我最终制定的解决方案涉及几个步骤,但据我所知是 "clean"。

  1. 将工厂函数放在文件中 R/aaa.R 以确保它在关闭之前加载。
  2. 将闭包使用的数据放入标准 inst/extdata/ 文件夹。
  3. 将包含闭包名称和正确文档字符串的文件放入 R/:将闭包定义为普通函数,只是 return 什么都没有。这是必要的,这样函数才能正确导出并在包命名空间中为人所知。立即调用工厂函数创建闭包并覆盖原来的定义。注意:仅仅将数据作为参数传入工厂函数是不够的,实际上需要在定义闭包之前访问它。为什么?那是因为延迟加载实际上不会将数据加载到您需要的环境中,除非您访问它。

就是这样。摘要:为您的闭包创建一个存根,然后用工厂函数的 return 值覆盖它。

如果工厂函数稍后被包用户调用

但我们仍然希望返回的闭包位于包内(例如,如果我们不希望它被除工厂以外的任何东西更改、可以从包内可靠地访问、记录等):

# exported function (visible to user)
# everything this function does is 'outsourced'
# to a non-exported function that we can overwrite with the factory:

visible_function(...){
   hidden_function(...)
}
# not exported function (invisible to the user)
# called by the visible function
# fails unless factory is called first
hidden_function(x){
 stop("call factory_fun() before you can use visible_function()")
}

# exported function, visible to the user.
# changes the hidden function called by the visible function
factory_function(x){
  produced_function<-function(){
     print(paste(x, "is an object forever stored in my namespace!"))
  }
   assignInNamespace("hidden_function",
                     produced_function,
                     ns="myPackageName")
}

请注意,R CMD 检查会在 assignInNamespace 上抛出一个注释,因此 CRAN 不会轻易接受此解决方案