Dynamically Generate Reference Classes

落花浮王杯 提交于 2019-12-18 14:49:39

问题


I'm attempting to generate reference classes within an R package on the fly, and it's proving to be fairly difficult. Here are the approaches I've taken and problems I've run into:

I'm creating a package in which I hope to be able to dynamically read in a schema and automatically generate an associated reference class (think SOAP). Of course, this means I won't be able to define my reference classes before-hand in the package sources.

I initially attempted to create a new class using a simple:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"))

which, of course, works fine when executed interactively, but when included in the package sources, I get a locked binding error. From my reading, it looks like this occurs because when running interactively, the class information is being stored in the global environment, which is not locked, while my package's base environment is locked.

I then found a thread that suggested using something to the effect of:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=globalenv())

This actually crashed R/Studio when I tried to build the package, so I don't have a log of the error it generated, unfortunately, but it certainly didn't work.

Next I tried creating a new environment within my package which I could use to store these reference classes. So I added a .classEnv <- new.env() line in my package sources (not inside of any function) and then attempted to use this class when creating a new reference class:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=.classEnv) 

This actually seemed to work OK, but generates the following warning:

> myClass <- setRefClass("NewClassName", where=.classEnv)
Warning message:
In getPackageName(where) :
  Created a package name, ‘2013-04-23 10:19:14’, when none found

So, for some reason, methods::getPackageName() isn't able to pick up which package my new environment is in?

Is there a way to create my new environment differently so that getPackageName() can properly recognize the package? Can I add some feature which allows me to help getPackageName() detect the package? Will this even work if I can deal with the warning, or am I misusing reference classes by trying to create them dynamically?


回答1:


To get the conversation going, I found that getpackageName stores the package name in a hidden .packageName variable in the specified environment.

So you can actually get around the warning with

assign(".packageName", "MyPkg", envir=.classEnv)    
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv)

which resolves the warning, but the documentation says not to trust the .packageName variable indefinitely, and I still feel like I'm hacking this in and may be misunderstanding something important about reference classes and their relationship to environments.

Full details from documentation:

Package names are normally installed during loading of the package, by the INSTALL script or by the library function. (Currently, the name is stored as the object .packageName but don't trust this for the future.)


Edit:

After reading a little further, the setPackageName method may be a more reliable way to set the package name for the environment. Per the docs:

setPackageName can be used to establish a package name in an environment that would otherwise not have one. This allows you to create classes and/or methods in an arbitrary environment, but it is usually preferable to create packages by the standard R programming tools (package.skeleton, etc.)

So it looks like one valid solution would be the following:

setPackageName("MyPkg", .classEnv)
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv)

That eliminates the warning message and doesn't rely on anything that's documented as unstable. I'm still not clear why it's necessary, but...



来源:https://stackoverflow.com/questions/16173658/dynamically-generate-reference-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!