R包的函数命名
Function naming for R packages
我正在编写一个 R 程序包,我真的很想避免使用在其他程序包中找到的函数名称。例如,我打算调用一个函数'annotate',但是这个已经在NLP包中使用了。显然最好避免明显的名称选择,但是是否有系统的方法来搜索 CRAN 发布的函数名称的详尽列表以避免重复?我很欣赏这对于 CRAN 共享包非常重要,但在本地共享时它也可能是相关的,以防与另一个加载的包发生冲突。
当加载两个包含同名函数的包时会发生名称冲突。因此,可以在两个地方避免名称冲突:
- 在包中定义函数名称时
- 从包中调用函数时
创建具有唯一名称的函数
在撰写本文时(2017 年 8 月 23 日),CRAN 上提供了数量惊人的 11272 个软件包(最新数据可在 here) and new packages are being added every day.
中找到
因此,在今天创建唯一的函数名称可能会在将来添加其他包时导致名称冲突。
为所有函数添加前缀的选项。除了 stringi
和 stringr
,forcats
包是另一个使用前缀 fct_
和 lvls_
.
的例子
这种方法可以大大降低名称冲突的可能性。
(虽然不能保证没有其他包维护者会选择相同的前缀。)
使用双冒号运算符明确调用函数
恕我直言,避免名称冲突的最终责任在于用户。
我在这里看到关于 SO 的问题,加载了超过六个包。或者,为方便起见调用 library(tidyverse)
,它加载了其他 19 个包,其中 dplyr
和 tidyr
就足够了。
用许多已加载的包使命名空间混乱会增加名称冲突的风险。即使只加载了两个包,名称冲突也可能发生。例如,lubridate
和 data.table
包都定义了
hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year
调用哪个函数将取决于包的加载顺序。 (您可以使用 conflicts()
来查找在搜索路径上两个或更多位置存在的同名对象。)
为了避免歧义和意外结果,我建议加载尽可能少的包,并使用双冒号运算符 ?"::"
从包中调用函数,而无需事先加载包,例如,
library(data.table)
DT <- data.table(t = lubridate::now() + 0:3)
# call function from loaded package data.table
DT[, second(t)]
[1] 18 19 20 21
# call function from lubridate package
DT[, lubridate::second(t)]
[1] 18.88337 19.88337 20.88337 21.88337
使用双冒号运算符还有另一个好处。它将在调用函数的包中的代码中充当文档。
这是以几次额外的击键为代价的,但在数周或数年后检查、修改或调试代码时可能会节省大量时间。我在 SO 上看到很多问题,其中 OP 没有提到包。
我正在编写一个 R 程序包,我真的很想避免使用在其他程序包中找到的函数名称。例如,我打算调用一个函数'annotate',但是这个已经在NLP包中使用了。显然最好避免明显的名称选择,但是是否有系统的方法来搜索 CRAN 发布的函数名称的详尽列表以避免重复?我很欣赏这对于 CRAN 共享包非常重要,但在本地共享时它也可能是相关的,以防与另一个加载的包发生冲突。
当加载两个包含同名函数的包时会发生名称冲突。因此,可以在两个地方避免名称冲突:
- 在包中定义函数名称时
- 从包中调用函数时
创建具有唯一名称的函数
在撰写本文时(2017 年 8 月 23 日),CRAN 上提供了数量惊人的 11272 个软件包(最新数据可在 here) and new packages are being added every day.
中找到因此,在今天创建唯一的函数名称可能会在将来添加其他包时导致名称冲突。
stringi
和 stringr
,forcats
包是另一个使用前缀 fct_
和 lvls_
.
这种方法可以大大降低名称冲突的可能性。
(虽然不能保证没有其他包维护者会选择相同的前缀。)
使用双冒号运算符明确调用函数
恕我直言,避免名称冲突的最终责任在于用户。
我在这里看到关于 SO 的问题,加载了超过六个包。或者,为方便起见调用 library(tidyverse)
,它加载了其他 19 个包,其中 dplyr
和 tidyr
就足够了。
用许多已加载的包使命名空间混乱会增加名称冲突的风险。即使只加载了两个包,名称冲突也可能发生。例如,lubridate
和 data.table
包都定义了
hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year
调用哪个函数将取决于包的加载顺序。 (您可以使用 conflicts()
来查找在搜索路径上两个或更多位置存在的同名对象。)
为了避免歧义和意外结果,我建议加载尽可能少的包,并使用双冒号运算符 ?"::"
从包中调用函数,而无需事先加载包,例如,
library(data.table)
DT <- data.table(t = lubridate::now() + 0:3)
# call function from loaded package data.table
DT[, second(t)]
[1] 18 19 20 21
# call function from lubridate package
DT[, lubridate::second(t)]
[1] 18.88337 19.88337 20.88337 21.88337
使用双冒号运算符还有另一个好处。它将在调用函数的包中的代码中充当文档。
这是以几次额外的击键为代价的,但在数周或数年后检查、修改或调试代码时可能会节省大量时间。我在 SO 上看到很多问题,其中 OP 没有提到包。