gpt4 book ai didi

r - R包:当我的导出函数未从其他包中显式调用函数,而子例程执行时,“import”的工作方式

转载 作者:行者123 更新时间:2023-12-02 02:56:01 25 4
gpt4 key购买 nike

我正在开发我的第一个R包,对于来说,对于我来说尚不清楚的东西是在Description文件中导入。我浏览了很多说明软件包结构的指南,但是找不到我的问题的答案,所以这是我的情况。

  • 我定义了要导出的函数f,因此其定义将在顶部带有正确的@export roxygen注释。
  • 现在
  • ,我的函数f调用了我不想导出的子例程hidden。函数hidden也使用其他软件包,例如X软件包。

  • 因为对 X的调用是在 hidden函数内部,所以我的函数 @import X中没有标签 f。因此,我在我的DESCRIPTION文件中的 X中添加了 Imports包,希望在那里指定相关的依赖项。

    但是,当我使用 devtools::document()时,生成的NAMESPACE不包含 X的条目。我可以看到发生这种情况的原因:解析器只是在roxygen注释中找不到 f的标志,并且在运行时对 f的调用崩溃,因为缺少 X

    现在,我可以通过在 X的导入中指定 f来修复所有问题。但是为什么机制如此棘手?或者,类似地,为什么我在DESCRIPTION中的导入与NAMESPACE中的导入不匹配?

    最佳答案

    我的理解是,有三种“正确”的方式来进行导入。 “正确”是指它们将通过CRAN检查并正常运行。选择哪个选项是要平衡各种优势,并且在很大程度上是主观的。

    我将在下面使用术语回顾这些选项

  • primary_function您要导出的包中的函数
  • hidden primary_function所使用的软件包中未导出的函数
  • thirdpartypkg::blackboxblackbox是从thirdpartypkg包中导出的函数。

  • 选项1(无直接导入/显式函数调用)

    我认为这是最常见的方法。在Description文件中声明了 thirdpartypkg,但是在NAMESPACE文件中没有从 thirdpartypkg导入任何内容。在此选项中, 所必需的,以便使用 thirdpartypkg::blackbox构造来获得所需的行为。
    # DESCRIPTION

    Imports: thirdpartypkg

    # NAMESPACE
    export(primary_function)


    #' @name primary_function
    #' @export

    primary_function <- function(x, y, z){
    # do something here
    hidden(a = y, b = x, z = c)
    }

    # Unexported function
    #' @name hidden

    hidden <- function(a, b, c){
    # do something here

    thirdpartypkg::blackbox(a, c)
    }

    选项2(直接导入/无显式函数调用)

    在此选项中,您直接导入 blackbox函数。这样做之后,就不再需要使用 thirdpartypkg::blackbox了;您可以简单地调用 blackbox,就好像它是软件包的一部分一样。 (从技术上讲,您将其导入了 namespace ,因此无需获取另一个 namespace 即可获取它)
    # DESCRIPTION

    Imports: thirdpartypkg

    # NAMESPACE
    export(primary_function)
    importFrom(thirdpartypkg, blackbox)


    #' @name primary_function
    #' @export

    primary_function <- function(x, y, z){
    # do something here
    hidden(a = y, b = x, z = c)
    }

    # Unexported function
    #' @name hidden
    #' @importFrom thirdpartypkg blackbox

    hidden <- function(a, b, c){
    # do something here

    # I CAN USE blackbox HERE AS IF IT WERE PART OF MY PACKAGE
    blackbox(a, c)
    }

    选项3(直接导入/显式函数调用)

    您的最后一个选项组合了前两个选项,并将 blackbox导入您的 namespace ,然后使用 thirdpartypkg::blackbox构造来利用它。从有效的意义上来说,这是“正确的”。但这可以说是浪费和多余的。

    我说这是浪费和多余的原因是,将 blackbox导入到您的 namespace 后,您再也不会使用它了。相反,您在 blackbox命名空间中使用了 thirdpartypkg。从本质上讲, blackbox现在存在于两个 namespace 中,但是只有其中一个已被使用。这就引出了为什么要完全制作副本的问题。
    # DESCRIPTION

    Imports: thirdpartypkg

    # NAMESPACE
    export(primary_function)
    importFrom(thirdpartypkg, blackbox)


    #' @name primary_function
    #' @export

    primary_function <- function(x, y, z){
    # do something here
    hidden(a = y, b = x, z = c)
    }

    # Unexported function
    #' @name hidden
    #' @importFrom thirdpartypkg blackbox

    hidden <- function(a, b, c){
    # do something here

    # I CAN USE blackbox HERE AS IF IT WERE PART OF MY PACKAGE
    # EVEN THOUGH I DIDN'T. CONSEQUENTLY, THE blackbox I IMPORTED
    # ISN'T BEING USED.
    thirdpartypkg::blackbox(a, c)
    }

    注意事项

    那么哪种才是最好的使用方法呢?确实没有一个简单的答案。我会说备选方案3可能不是采取的方法。我可以告诉你,Wickham建议不要使用选项3(我一直在该框架下进行开发,而他建议我反对该选项)。

    如果我们在选项1和选项2之间进行选择,我们必须考虑的因素是1)编写代码的效率,2)读取代码的效率和3)执行代码的效率。

    在提高代码编写效率方面,通常使用 @importFrom thirdpartypkg blackbox更容易,并且避免使用 ::运算符。它只保存了一些按键。但是,这不利地影响了代码的可读性,因为现在尚不清楚 blackbox的来源。

    在读取代码的效率方面,最好省略 @importFrom并使用 thirdpartypkg::blackbox。这使得 blackbox的来源很明显。

    关于执行代码的效率,最好使用 @importFrom。调用 thirdpartypkg::blackbox比使用 @importFrom和调用 blackbox慢约0.1毫秒。那不是很多时间,所以可能不是很多考虑。但是,如果您的程序包使用了数百个 ::构造,然后陷入循环或重采样过程,那么这些毫秒数可能会开始累加。

    最终,我认为我读过的最佳指南(并且我不知道在哪里)是,如果您要多次调用 blackbox,那么值得使用 @importFrom。如果在一个包中只调用三到四次,请继续使用 ::构造。

    关于r - R包:当我的导出函数未从其他包中显式调用函数,而子例程执行时,“import”的工作方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49427767/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com