我正在尝试在 R 包中动态生成引用类,事实证明这相当困难。以下是我采取的方法和遇到的问题:
我正在创建一个包,我希望能够在其中动态读取模式并自动生成关联的引用类(想想 SOAP)。当然,这意味着我将无法在包源中预先定义我的引用类。
我最初尝试使用一个简单的方法创建一个新类:
myClass <- setRefClass("NewClassName", fields=list(fieldA="character"))
当然,当以交互方式执行时,它工作正常,但是当包含在包源中时,我收到
locked binding
错误。从我的阅读来看,发生这种情况是因为在交互运行时,类信息存储在全局环境中,未锁定,而我的包的基础环境已锁定。然后我发现一个线程建议使用一些东西来达到以下效果:
myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=globalenv())
当我尝试构建包时,这实际上使 R/Studio 崩溃了,所以我没有它生成的错误的日志,不幸的是,但它肯定不起作用。
接下来,我尝试在我的包中创建一个新环境,我可以用它来存储这些引用类。所以我在我的包源中添加了
.classEnv <- new.env()
行(不在任何函数内部),然后在创建新的引用类时尝试使用这个类:myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=.classEnv)
这实际上似乎工作正常,但会产生以下警告:
> myClass <- setRefClass("NewClassName", where=.classEnv)
Warning message:
In getPackageName(where) :
Created a package name, ‘2013-04-23 10:19:14’, when none found
那么,出于某种原因,
methods::getPackageName()
无法获取我的新环境在哪个包中?有没有办法以不同的方式创建我的新环境,以便
getPackageName()
可以正确识别包?我可以添加一些功能来帮助 getPackageName()
检测包裹吗?如果我可以处理警告,这甚至会起作用,或者我是否通过尝试动态创建引用类来滥用引用类? 最佳答案
为了让对话继续下去,我发现 getpackageName
将包名称存储在指定环境中的隐藏 .packageName
变量中。
所以你实际上可以绕过警告
assign(".packageName", "MyPkg", envir=.classEnv)
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv)
这解决了警告,但文档说不要无限期地信任
.packageName
变量,我仍然觉得我在破解这个,并且可能误解了一些关于引用类及其与环境关系的重要内容。文档中的完整详细信息:
编辑 :
进一步阅读后,
setPackageName
方法可能是为环境设置包名称的更可靠的方法。根据文档:所以看起来一个有效的解决方案如下:
setPackageName("MyPkg", .classEnv)
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv)
这消除了警告消息,并且不依赖任何记录为不稳定的内容。我仍然不清楚为什么有必要,但是......
关于r - 动态生成引用类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16173658/