簡體   English   中英

R包:當導出的函數沒有顯式調用其他包中的函數時,“導入”如何工作,但子例程卻如此

[英]R Package: how “import” works when my exported function does not call explicitly a function from other packages, but a subroutine does

我正在開發我的第一個R包,並且有一些東西我不清楚描述文件中的Imports 我經歷了一些解釋包結構的指南,但我沒有找到問題的答案,所以這是我的情況。

  • 我定義了一個我將導出的函數f ,因此它的定義將在頂部有正確的@export roxygen注釋。
  • 現在,我的函數f調用一個hidden的子程序,我不想導出。 函數hidden使用其他包,比如包X

因為對X的調用是hidden函數內部,所以函數f沒有@import X標記。 因此,我將包X添加到我的DESCRIPTION文件中的Imports ,希望在那里指定相關的依賴項。

但是,當我使用devtools::document()時,生成的NAMESPACE不包含X的條目。 我可以看到為什么會發生這種情況:解析器在f的roxygen注釋中找不到標志,並且在運行時調用f因為X丟失而崩潰。

現在,我可以通過在導入f指定X來修復所有內容。 但為什么這個機制很棘手? 或者,同樣地,為什么我在DESCRIPTION中的導入與NAMESPACE中的導入不匹配?

我的理解是有三種“正確”的方法來進行導入。 通過“正確”,我的意思是他們將通過CRAN檢查並正常運行。 您選擇哪個選項是平衡各種優勢的問題,並且主要是主觀的。

我將使用術語查看以下這些選項

  • primary_function您要導出的包中的函數
  • hiddenprimary_function使用的包中未導出的函數
  • thirdpartypkg::blackboxblackboxthirdpartypkg包中的導出函數。

選項1(沒有直接導入/顯式函數調用)

我認為這是最常見的方法。 thirdpartypkg在DESCRIPTION文件中聲明,但在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稱為你的包的一部分。 (從技術上講,它是將它導入命名空間,因此不需要到達另一個命名空間來獲取它)

# 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導入您的命名空間,但隨后使用thirdpartypkg::blackbox構造來使用它。 從它起作用的意義上說,這是“正確的”。 但它可以被認為是浪費和多余的。

我說這是浪費和多余的原因是,將blackbox導入您的命名空間后,您永遠不會使用它。 相反,您正在使用thirdpartypkg命名空間中的blackbox 從本質上講, blackbox現在存在於兩個名稱空間中,但只使用其中一個名稱空間。 這引出了為什么要制作副本的問題。

# 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並使用@importFrom thirdpartypkg::blackbox 這使得blackbox來自哪里顯而易見。

在執行代碼的效率方面,最好是@importFrom 調用thirdpartypkg::blackbox比使用@importFrom並調用blackbox慢約0.1毫秒。 這不是很多時間,所以可能不是很重要。 但是如果你的包使用了數百個:: constructs然后被拋入循環或重新采樣過程,那么這些毫秒就可以開始加起來了。

最后,我認為我讀過的最好的指導(我不知道在哪里)是,如果你打算多次打電話給blackbox ,那么值得使用@importFrom 如果您只在包中調用三到四次,請繼續使用:: construct。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM