短版
对于那些不想通读我的" case "的人来说,这是关键:
- 建议采用什么方法来最大限度地减少新包 destruct 现有代码的可能性,即使您编写的代码达到as robust as possible?
-
什么是最好地利用namespace mechanism的推荐方式
a) 只有using个贡献的包(比如在一些R分析项目中)?
b) 关于developing个自己的包裹?
如何最好地避免与formal classes(在我的例子中主要是Reference Classes)的冲突,因为对于类(AFAIU)甚至没有一个与
::
类似的命名空间机制?
R宇宙的运作方式
这件事在我的脑海里萦绕了大约两年,但我觉得自己并没有找到一个令人满意的解决方案.而且我觉得情况越来越糟了.
我们看到,CRAN、github、R-Forge等的软件包数量不断增加,这简直太棒了.
在这样一个分散的环境中,组成R的代码库(为了简单起见,假设是base R和contributed R)自然会偏离健壮性方面的理想状态:人们遵循不同的约定,有S3、S4、S4引用类,等等.如果有一个"central clearing instance"强制执行约定,事情就不会像它们那样"一致".没关系.
问题
鉴于上述情况,使用R编写健壮的代码可能非常困难.并不是所有你需要的东西都在base R中.对于某些项目,你最终会加载相当多的贡献包.
IMHO, the biggest issue in that respect is the way the namespace concept is put to use in R: R allows for simply writing the name of a certain function/method without explicitly requiring it's namespace (i.e. 100 vs. 101)
所以为了简单起见,每个人都在这么做.但这样一来,名称冲突、代码中断和重写/重构代码的需要只是时间问题(或加载的不同包的数量).
充其量,您将了解哪些现有函数被新添加的包屏蔽/重载.在最坏的情况下,在代码中断之前,您将没有任何线索.
举几个例子:
- 试着同时加载RMySQL和RSQLite,它们运行得不太好
- RMongo也将覆盖RMySQL的某些功能
- forecast屏蔽了很多与ARIMA相关的功能
-
R.utils甚至掩盖了
base::parse
的常规
(我不记得是哪些功能导致了这些问题,但如果有兴趣,我愿意再次查找)
令人惊讶的是,这似乎并没有困扰很多程序员.我试着在r-devel岁时提高几次兴趣,但都没有什么效果.
Downsides of using the ::
operator
- 在某些情况下,使用
::
运算符可能会显著降低效率,如Dominick Samperi pointed out. - 当您创建自己的包时,您甚至不能在自己的代码中使用
::
运算符,因为您的代码还不是真正的包,因此也没有名称空间.因此,我首先必须坚持foo
方式,构建、测试,然后回到将所有内容更改为namespace::foo
.不是真的.
避免这些问题的可能解决方案
-
Reassign将每个包中的每个函数转换为遵循特定命名约定的变量,例如
namespace..foo
,以避免与namespace::foo
相关的低效率(我曾在here中对其进行了概述).优点:很有效.缺点:这很笨拙,而且你使用的内存增加了一倍. - Simulate在开发包时使用名称空间.阿福,这真的不可能,至少我当时told so back then岁.
- 使用
namespace::foo
使其成为mandatory.嗯,那是最好的办法.当然,我们会失go 一定程度的简单性,但R宇宙也不再简单(至少不像20世纪初那么简单).
那么(正式)课程呢?
除了上述方面之外,::
-way对于函数/方法也非常有效.但是关于类定义呢?
带上timeDate
班的timeDate号Package.假设另一个包也有timeDate
类.我看不出我如何能明确地声明我希望从这两个包中的任何一个获得类timeDate
的新实例.
这样的事情是行不通的:
new(timeDate::timeDate)
new("timeDate::timeDate")
new("timeDate", ns="timeDate")
这可能是一个巨大的问题,因为越来越多的人在R包中使用OOP风格,导致了大量的类定义.如果有一种方法可以显式地处理类定义的名称空间,我将非常感谢一个指针!
结论
尽管这有点冗长,但我希望我能够指出核心问题,并在这里提高更多意识.