简洁版本
对于那些不想阅读我的“案例”的人来说,这就是本质:
- 最小化新包破坏现有代码(即编写您编写的代码)的机会的推荐方法是什么尽可能坚固?
-
充分利用该功能的推荐方法是什么?命名空间机制 when
a) just using贡献的软件包(比如在一些 R 分析项目中)?
b) 关于发展自己的包?
如何最好地避免冲突正式课程(大多参考类 http://stat.ethz.ch/R-manual/R-devel/library/methods/html/refClass.html在我的例子中)因为甚至没有一个命名空间机制可以与::
上课(AFAIU)?
R 宇宙的运作方式
这件事已经在我的脑海里萦绕了大约两年,但我觉得我似乎没有找到令人满意的解决方案。而且我感觉情况越来越糟了。
我们看到网上的包裹数量不断增加CRAN http://cran.at.r-project.org/web/packages/available_packages_by_name.html, github https://github.com/, R-Forge http://r-forge.r-project.org/等等,这简直太棒了。
在这样一个去中心化的环境中,组成 R 的代码库(假设是base R and 贡献R为简单起见)将偏离鲁棒性方面的理想状态:人们遵循不同的约定,有 S3、S4、S4 参考类等。事物不可能像存在“对齐”那样“对齐”中央清算实例“这强制执行了约定。没关系。
问题
鉴于上述情况,使用 R 编写健壮的代码可能非常困难。并非您需要的所有内容都会在基础 R 中。对于某些项目,您最终将加载相当多的贡献包。
恕我直言,这方面最大的问题是命名空间概念在 R 中的使用方式:R 允许简单地编写某个函数/方法的名称,而无需明确要求其命名空间(即foo
vs. namespace::foo
).
因此,为了简单起见,这就是每个人都在做的事情。但这样一来,名称冲突、损坏的代码以及重写/重构代码的需要只是时间问题(或加载的不同包数量的问题)。
最好的情况下,你会know关于哪些现有函数被新添加的包屏蔽/重载。最坏的情况是,在代码损坏之前您将一无所知。
举几个例子:
- 尝试加载RMySQL http://cran.at.r-project.org/web/packages/RMySQL/index.html and RSQLite http://cran.at.r-project.org/web/packages/RSQLite/index.html与此同时,他们相处得不太好
- also RMongo http://cran.at.r-project.org/web/packages/RMongo/index.html将覆盖某些功能RMySQL http://cran.at.r-project.org/web/packages/RMySQL/index.html
-
forecast http://cran.at.r-project.org/web/packages/forecast/index.html掩盖了很多与 ARIMA 相关函数相关的内容
-
R.utils http://cran.at.r-project.org/web/packages/R.utils/index.html甚至掩盖
base::parse
常规
(我不记得具体是哪些功能导致了问题,但如果有兴趣,我愿意再次查找)
令人惊讶的是,这似乎并没有困扰很多程序员。我曾多次尝试提高兴趣r-devel http://tolstoy.newcastle.edu.au/R/e15/devel/11/08/0416.html,没有太大作用。
使用的缺点::
操作员
- 使用
::
在某些情况下,操作员可能会严重损害效率,如多米尼克·桑佩里 (Dominick Samperi)指出 http://tolstoy.newcastle.edu.au/R/e15/devel/11/10/0716.html.
- When 发展你自己的包,你甚至不能使用
::
运算符贯穿您自己的代码,因为您的代码还不是真正的包,因此还没有命名空间。所以我最初必须坚持foo
方式,构建,测试,然后返回将所有内容更改为namespace::foo
。并不真地。
避免这些问题的可能解决方案
-
Reassign每个包中的每个函数到一个遵循特定命名约定的变量,例如
namespace..foo
为了避免与相关的低效率namespace::foo
(我概述过一次here http://tolstoy.newcastle.edu.au/R/e15/devel/11/08/0416.html)。优点:它有效。缺点:它很笨拙,而且使用的内存会增加一倍。
-
Simulate开发包时的命名空间。 AFAIU,这真的不可能,至少我是那时就这么说过 http://tolstoy.newcastle.edu.au/R/e13/devel/11/01/0039.html.
- Make it 强制的 to use
namespace::foo
。恕我直言,那将是最好的选择。当然,我们会失去一定程度的简单性,但话又说回来,R 宇宙不再简单了(至少不像 00 年代初那么简单)。
那么(正式)课程呢?
除了上述几个方面之外,::
方式对于函数/方法来说效果很好。但是类定义又如何呢?
取包裹timeDate http://cran.at.r-project.org/web/packages/timeDate/index.html与它的班级timeDate
。假设另一个包也有一个类timeDate
。我不明白如何明确声明我想要一个新的类实例timeDate
来自两个包中的任何一个。
像这样的事情是行不通的:
new(timeDate::timeDate)
new("timeDate::timeDate")
new("timeDate", ns="timeDate")
随着越来越多的人转向 OOP 风格的 R 包,这可能是一个大问题,导致大量的类定义。如果有is一种显式寻址类定义的名称空间的方法,我非常感谢指针!
结论
尽管这有点长,但我希望我能够指出核心问题,并且我可以在这里提高更多的认识。
I think devtools http://cran.at.r-project.org/web/packages/devtools/index.html and mvbutils http://cran.at.r-project.org/web/packages/mvbutils/index.html确实有一些可能值得传播的方法,但我确信还有更多要说的。