【问题标题】:Dealing with intentional NAMESPACE conflicts处理故意的命名空间冲突
【发布时间】:2019-02-11 05:49:16
【问题描述】:

我正在编写一个导入(并使用)SparkR::sqldbplyr::sql 的包。其他relevantquestions 涉及无意的碰撞,导致我随意的importing。

在我的NAMESPACE 我有:

importFrom(dbplyr, sql)
importFrom(SparkR, sql)

这两个函数都在脚本中使用,考虑到冲突,我肯定总是在包名前加上前缀:

dbplyr::sql(...)
SparkR::sql(...)

尽管如此,我在构建/检查包时收到了导入替换警告:

警告:加载“my_pkg”时,将之前的导入“dbplyr::sql”替换为“SparkR::sql”

我在Writing R Extensions 中看到的内容似乎如下:

如果一个包只需要另一个包中的几个对象,它可以在代码中使用完全限定的变量引用 [foo::f] 而不是正式导入...这比正式导入效率略低,而且也会丢失将所有依赖项记录在NAMESPACE 文件中的优点(但它们仍然需要记录在DESCRIPTION 文件中)。评估 foo::f 将导致包 foo 被加载,但如果尚未加载,则不会附加该包 - 这可能是延迟加载很少使用的包的优势。

我认为这个/最佳实践的要点是:

  • 选择最常用的函数并将其添加到importFrom
  • importFrom 中删除“不太频繁”的功能,但将该包保留在DESCRIPTION
  • 只需使用::(可能前面有require())作为“不太频繁”的功能

【问题讨论】:

  • 我认为(尤其是在这种情况下)我总是使用:: 表示法,即使一个明确地在NAMESPACE 中...为了清楚起见,如果没有别的。我同意被告知“你应该把它放在NAMESPACE”然后在故意的时候得到警告似乎是违反直觉的。只是我的 2 美分。

标签: r r-package dbplyr name-collision


【解决方案1】:

我一直关注this advice

包在描述中的导入中列出是很常见的,但在命名空间中却没有。事实上,我建议这样做:在DESCRIPTION中列出软件包以便安装它,然后始终使用pkg::fun()显式引用它。

在你的情况下:

  • 删除两者 importFrom
  • 将两个包保存在Imports:
  • 使用dbplyr::sqlSparkR::sql

我在这里的主要动机是一致性:即使没有任何名称冲突,我也希望在阅读代码时始终使用全名以明确某些函数的来源。如果我不使用importForm 并忘记在一个地方使用全名,R CMD ckeck 会抓住这一点。我认为这种代码清晰度高于在两个地方收集依赖项的(感知的)优势:描述和(更明确的)命名空间。

【讨论】:

  • 这与官方的建议背道而驰,当然:“[使用::] 比正式导入的效率略低,并且也失去了在NAMESPACE 文件中记录所有依赖项的优势”
  • @MichaelChirico 同意,但即使在没有名称冲突的情况下,我发现源代码的可读性更重要,c.f.我的扩展答案。
  • 我可以在代码旁边评论正在使用哪个函数并且仍然可以获得importFrom的效率增益
  • @MichaelChirico 对我来说,这样的评论会构成代码异味。但这只是我的意见,所以我会在这里停下来。
猜你喜欢
  • 2010-12-05
  • 2010-09-20
  • 1970-01-01
  • 2013-01-26
  • 2010-11-15
  • 2012-12-18
  • 2012-02-06
  • 1970-01-01
相关资源
最近更新 更多