【问题标题】:Better explanation of when to use Imports/Depends更好地解释何时使用 Imports/Depends
【发布时间】:2012-01-28 02:36:12
【问题描述】:

Writing R Extensions”手册就何时使用 Imports 或 Depends 提供以下指导:

一般规则是

  • 使用 library(pkgname) 加载包时仅需要命名空间的包必须列在“Imports”字段中,而不是列在 “取决于”字段。
  • 需要附加以使用 library(pkgname) 成功加载包的包必须仅列在“依赖”字段中。

有人可以对此提供更清晰的说明吗?我如何知道我的包何时只需要加载命名空间以及何时需要附加一个包?两者都有哪些例子?我认为典型的包只是函数的集合,这些函数有时会调用其他包中的函数(其中一些工作已经被编码)。这是上面的场景 1 还是 2?

编辑

我写了一封blog post,其中有一个关于这个特定主题的部分(搜索“Imports v Depends”)。视觉效果更容易理解。

【问题讨论】:

  • 你的博文告诉了我关于包结构的一切,早在我开始计划 modules 时。谢谢!

标签: r


【解决方案1】:

"Imports""Depends" 更安全(并且相对于使用 "Depends" 的其他软件包,使用它的软件包也成为“更好的公民”)。

"Depends" 指令试图通过将另一个包附加到主搜索路径(即search() 返回的环境列表)来确保来自另一个包的功能可用。但是,如果稍后加载的另一个包在搜索路径上较早地放置了相同名称的函数,则此策略可能会受到阻碍。 Chambers (in SoDA) 使用了函数"gam" 的示例,该函数在gammgcv 包中都可以找到。如果加载了另外两个包,其中一个依赖于gam,一个依赖于mgcv,通过调用gam() 找到的函数将取决于它们附加这两个包的顺序。不好。

"Imports" 指令应用于任何支持包,其功能将放在<imports:packageName>(紧跟在<namespace:packageName> 之后搜索),而不是常规搜索路径。如果上面示例中的任何一个包使用了"Imports" 机制(这也需要NAMESPACE 文件中的importimportFrom 指令),那么问题将通过两种方式得到改善。 (1) 包本身将控制使用哪个mgcv 函数。 (2) 通过保持主搜索路径不包含导入的对象,它甚至不会破坏其他包对其他 mgcv 函数的依赖。

这就是为什么使用命名空间是一种很好的做法,为什么它现在被 CRAN 强制执行,以及(特别是)为什么使用 "Imports" 比使用 "Depends" 更安全。


编辑添加了一个重要的警告:

不幸的是,上面的建议有一个一个常见的例外:如果您的包依赖于一个包A,而该包本身是"Depends",另一个包B,您的包可能需要附加A 带有 "Depends 指令。

这是因为A 包中的函数在编写时期望包B 及其函数将附加到search() 路径

"Depends" 指令将加载并附加包A,此时包A 自己的"Depends" 指令将在连锁反应中导致包B 也被加载和附加.然后,包A 中的函数将能够找到它们所依赖的包B 中的函数。

"Imports" 指令将加载但附加包A 并且将既不加载也不附加包B。 (毕竟,"Imports" 期望包编写者使用命名空间机制,并且包A 将使用"Imports" 指向它需要访问的B 中的任何函数。)由你的函数调用到包A 中依赖包B 中的函数的任何函数将因此失败。

唯一的两个解决方案是:

  1. 使用"Depends" 指令让您的包附加包A
  2. 从长远来看,最好联系包 A 的维护者,并要求他们更仔细地构建命名空间(用 this related answer 中的 Martin Morgan 的话来说)。

【讨论】:

  • 最近提出了一个类似的问题,并且最近与这些问题进行了激烈的角力,这些都是微妙且经常沟通不畅的概念。我会在这里向您推荐另一种解释:stackoverflow.com/questions/7880355/…
  • @BryanHanson -- 感谢您在该链接上写下笔记。 ImportsDepends w.r.t 之间的区别。 .Rd 文件中的版本要求和示例检查确实很微妙,值得了解。
  • 有关使用“依赖”的依赖项的警告是一件可怕的事情。这意味着我基本上不能在我的包中使用“进口”,直到其他人也一样。 =(
  • 这似乎与 Hadley Wickham 在这里的解释相反:r-pkgs.had.co.nz/namespace.html#imports。他从字面上说:“Imports 字段实际上与导入命名空间的函数无关”。如果我理解正确,说明文件的导入部分仅确保在安装包时安装包。如果你想在你的包中使用它的功能(不使用 ::),你需要在 NAMESPACE 文件中包含一个包。还是我错过了什么?
  • @Willem 谢谢。您当然是正确的,我已经编辑了答案以清除误导性内容。让这个问题难以回答的部分原因是,虽然 OP 参考 DESCRIPTIONDependsImports 部分提出了他的问题,但他实际上是在问什么“导入”函数(而不是“取决于" 上) 的意思。由于后者是我试图回答的问题(而且——我怀疑——大多数搜索这个答案的人都想知道什么),否则我将保持答案不变。
【解决方案2】:

这里有一个简单的问题可以帮助您决定使用哪个:

您的软件包是否要求最终用户能够直接访问另一个软件包的功能?

  • 否 -> 进口(最常见的答案)
  • 是 -> 取决于

您应该使用“Depends”的唯一情况是当您的包是另一个包的附加组件或伴侣时,您的最终用户将在他们的代码中使用您的包和“Depends”包中的函数。如果您的最终用户只会与您的函数交互,而另一个包只会在幕后工作,那么请改用“导入”。

需要注意的是,如果您像往常一样将包添加到“Imports”,您的代码将需要使用完整的命名空间语法来引用该包中的函数,例如dplyr::mutate(),而不仅仅是mutate()。它使代码阅读起来有些笨拙,但要为更好的包装卫生付出很小的代价。

【讨论】:

    【解决方案3】:

    Hadley Wickham 给出了一个简单的解释 (http://r-pkgs.had.co.nz/namespace.html):

    DependsImports 中列出一个包可以确保它是 需要时安装。 主要区别在于 Imports 只是 加载包,Depends 附加它。没有其他的 差异。 [...]

    除非有充分的理由,否则您应该始终列出 Imports 不是 Depends 中的包。 那是因为一个好的包是 自给自足,并最大限度地减少对全球环境的变化 (包括搜索路径)。 唯一的例外是您的包裹是 旨在与另一个包一起使用。例如, 模拟包建立在素食主义者之上。没有它是没有用的 素食主义者,所以它在Depends而不是Imports中有素食主义者。相似地, ggplot2 应该真正依赖于比例,而不是导入它。

    【讨论】:

      【解决方案4】:

      SfDA 中的钱伯斯说当这个包使用“命名空间”机制时使用“导入”,并且由于现在所有包都需要拥有它们,那么现在的答案可能总是使用“导入”。在过去,可能已经加载了包而实际上没有命名空间,在这种情况下,您需要使用 Depends。

      【讨论】:

      • 当在“imports”中指定了一个包并且我想使用包中的一个函数时,我自己的函数需要调用 library(...) 还是所有函数都已经在搜索路径?另外,什么是 SfDA?链接?
      • 数据分析软件springer.com/statistics/computanional+statistics/book/… ...至于你的问题,我不知道答案,但你可以很好地破解一个最小的测试包轻松并凭经验找到答案...
      • SfDA == "数据分析软件"。 [65]r-project.org/doc/bib/R-books.html。如果一个包指定了另一个包,当您在控制台使用 library() 或 require() 时,您应该会看到一条消息,告诉您有关依赖项(encies)和 import(ations) 的加载。是的,它们应该可用。
      • +1 -- 这也是我的强烈印象。此外,将在 <namespace:packageName> 之后立即搜索导入中指定的包,作为 <imports:packageName> 的一部分。不需要进一步调用library(),并且R 不会在包加载时在控制台通知您,除非找不到Imported 包。
      猜你喜欢
      • 2011-01-09
      • 2016-12-08
      • 1970-01-01
      • 2013-04-21
      • 2016-06-21
      • 1970-01-01
      • 2015-05-18
      • 1970-01-01
      相关资源
      最近更新 更多