![](/img/trans.png)
[英]Same R function works as function/object in Global Env, does not work when loaded from R package
[英]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
您要導出的包中的函數 hidden
了primary_function
使用的包中未導出的函數 thirdpartypkg::blackbox
, blackbox
是thirdpartypkg
包中的導出函數。 我認為這是最常見的方法。 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)
}
在此選項中,您可以直接導入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)
}
您的最后一個選項結合了前兩個選項並將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.