Kun*_*Ren 39 scope namespaces r scoping qualified-name
我正在写使用一些有用的功能像其他一些包R里面的函数stringr
和base64enc
.是不是首先要调用library(...)
或者require(...
加载这些包,而是::
用来直接引用我需要的函数,比如stringr::str_match(...)
?
在一般情况下这是一个好习惯吗?或者它会引起什么问题?
Gre*_*gor 49
这一切都取决于背景.
::
如果存在命名空间冲突,则来自具有相同名称的不同包的函数是主要必需的.当我加载dplyr
包时,它提供了一个函数filter
,该filter
函数与stats
包中默认加载的函数相冲突(并屏蔽).所以如果我想使用该stats
函数的版本,我需要调用它stats::filter
.这也为不加载大量软件包提供了动力.如果你真的只想要一个包中的一个函数,那么使用它::
比加载整个包更好,特别是如果你知道包会掩盖你想要使用的其他函数.
不是在代码中,而是在文本中,我觉得::
非常有用.键入stats::filter
比" 包中的filter
功能" 简洁得多stats
.
从性能角度来看,使用的价格非常低::
.Martin Maechler写道(在r-devel邮件列表上(2017年9月))
许多人似乎忘记了每次使用
::
都是一个R函数调用,与仅使用已导入的名称相比,使用它是低效的.
性能损失非常小,大约几微秒,因此当您需要高度优化的代码时,这只是一个问题.运行使用::
一百万次的代码行将比不使用的代码长一两秒::
.
就可移植性而言,在脚本顶部显式加载包是很好的,因为它可以很容易地浏览前几行,看看需要哪些包,必要时安装它们,然后再深入其他任何包,即,如果没有重新开始,现在就无法完成一个漫长的过程.
除了:一个类似的说法可以做出更喜欢library()
过require()
.如果包不存在,库将导致错误并停止,而require将发出警告但仍继续.如果您的代码有一个应急计划,以防包裹不在那里,那么一定要使用if (require(package)) ...
,但是如果您的代码在没有包的情况下失败,您应该library(package)
在顶部使用,以便尽早及清楚地失败.(感谢Hugh和BondedDust的评论.)
一般的解决方案是使您自己的包imports
与您需要在DESCRIPTION文件中使用的其他包.安装软件包时将自动安装这些软件包,因此您可以在pkg::fun
内部使用.或者,通过在NAMESPACE
文件中导入它们,您可以import
整个包或选择性importFrom
特定功能而不需要::
.意见不同.R-Core成员Martin Maechler(与上述相同的r-devel来源)说:
就个人而言,我得到的印象是::是多"过度使用"的今天,特别是在包哪里我强烈主张使用importFrom()中的命名空间,所以这一切都发生在包加载时间,然后不使用
::
的包源本身.
另一方面,着名的软件包开发人员Hadley Wickham在他的R Packages书中说:
这是常见的事情被列出的软件包
Imports
中DESCRIPTION
,而不是在NAMESPACE
.事实上,这就是我的建议:列出软件包DESCRIPTION
以便安装它,然后总是明确地引用它pkg::fun()
.除非有充分的理由不这样做,否则最好是明确的.
有两位受人尊敬的R专家给出了相反的建议,我认为你应该选择最适合你的风格,并满足你对清晰度,效率和可维护性的需求.
如果您经常发现自己只使用另一个包中的一个函数,则可以复制代码并将其添加到您自己的包中.例如,我有一个个人使用%nin%
的Hmisc
包,借用了包,因为我认为这是一个很好的功能,但我不经常使用其他任何东西Hmisc
.使用roxygen2
,可以轻松添加@author
并@references
正确归属借用函数的代码.执行此操作时,还要确保包许可证兼容.