“Writing R Extensions”手册提供了有关何时使用进口或取决的以下指导:
一般规则是
- 必须在“Imports”字段中列出仅使用库(pkgname)加载包的名称空间的软件包,而不是 '取决于'领域。
- 需要附加以使用库(pkgname)成功加载包的软件包必须仅在“取决于”字段中列出。
有人可以提供一点清晰度吗?我如何知道我的软件包何时只需要加载名称空间,何时需要附加软件包?两者的例子是什么?我认为典型的包只是一组函数,有时会调用其他包中的函数(其中一些工作已被编码)。这个场景是上面的1还是2?
修改
我写了一篇blog post,其中有关于此特定主题的部分(搜索“Imports v Depends”)。视觉效果使其更容易理解。
答案 0 :(得分:131)
"Imports"
比"Depends"
更安全(并且使用"Depends"
的其他软件包使用它成为'更好的公民')。
"Depends"
指令尝试通过将其他包附加到主搜索路径(即search()
返回的环境列表)来确保来自另一个包的函数可用。但是,如果稍后加载的另一个包在搜索路径上更早地放置一个具有相同名称的函数,则可以阻止此策略。 Chambers(in SoDA)使用函数"gam"
的示例,该函数可在gam
和mgcv
包中找到。如果加载了其他两个包,其中一个取决于gam
,另一个取决于mgcv
,则调用gam()
找到的函数将取决于这两个包的顺序连接。不好。
"Imports"
指令将导入的包放在<imports:packageName>
中(在<namespace:packageName>
之后立即搜索),而不是常规搜索路径。如果上面示例中的任何一个软件包使用"Imports"
机制,则可以通过两种方式改进问题。 (1)包本身可以控制使用mgcv
函数。 (2)通过保持主搜索路径不受导入对象的影响,它甚至不会破坏其他包对其他mgcv
函数的依赖。
这就是为什么使用名称空间是一种很好的做法,为什么它现在由CRAN强制执行,并且(特别)为什么使用"Imports"
比使用"Depends"
更安全。
编辑添加了一个重要警告:
上面的建议有一个一个不幸的例外情况:如果您的软件包依赖于另一个软件包A
上自己为"Depends"
的软件包B
,那么包可能需要附加A
"Depends
指令。
这是因为编写了包A
中的函数,期望包B
及其函数将附加到search()
路径。< / p>
"Depends"
指令将加载并附加包A
,此时包A
自己的"Depends"
指令将在链式响应中导致包{{} 1}}也可以加载和附加。然后,包B
中的函数将能够找到它们所依赖的包A
中的函数。
B
指令将加载,但不附加包"Imports"
, {1}}。 (A
,毕竟,期望包编写者使用命名空间机制,并且包B
将使用"Imports"
指向A
中需要的任何函数访问。)函数调用包"Imports"
中依赖于包B
中的函数的任何函数都将失败。
唯一的解决方案是:
A
指令让您的包附加包B
。A
的维护者,并要求他们更细致地构建命名空间(用this related answer中的Martin Morgan的话来说)。答案 1 :(得分:29)
Hadley Wickham给出了一个简单的解释(http://r-pkgs.had.co.nz/namespace.html):
在
Depends
或Imports
中列出一个包,确保它是 在需要时安装。主要区别在于Imports
加载包,Depends
附加它。没有别的 差异。 [...]除非有充分的理由,否则你应该总是列出
Imports
中的软件包不是Depends
。那是因为一个好的软件包 自足,并最大限度地减少对全球环境的影响 (包括搜索路径)。 唯一的例外是你的包裹 旨在与另一个包装一起使用。例如, 模拟包建立在素食主义者之上。没有它就没有用 素食主义者,所以它在Depends
而不是Imports
有素食主义者。同样的, ggplot2应该真的取决于规模,而不是导入它。
答案 2 :(得分:14)
SfDA的钱伯斯表示要使用&#39; Imports&#39;当这个包使用&#39;命名空间时#39;机制,因为现在所有包都需要它们,所以答案现在可能总是使用&#39; Imports&#39;。在过去,可以加载包而不需要实际拥有名称空间,在这种情况下,您需要使用Depends。
答案 3 :(得分:3)
这是一个简单的问题,可以帮助您决定使用哪个:
您的软件包是否要求最终用户直接访问其他软件包的功能?
您应该使用的唯一时间&#39;取决于&#39;当您的软件包是其他软件包的附加软件或附件时,您的最终用户将使用您的软件包中的功能,并且取决于&#39;取决于&#39;在他们的代码中打包。如果您的最终用户只与您的功能接口,而另一个套件只在幕后工作,那么请使用&#39; Imports&#39;代替。
需要注意的是,如果您像往常一样将软件包添加到&#39; Imports&#39;,您的代码将需要使用完整的命名空间语法(例如,使用完整的命名空间语法)来引用该软件包中的函数。 dplyr::mutate()
,而非mutate()
。它使代码看起来有点笨拙,但是为了更好的包装卫生,这是一个很小的代价。