繁体   English   中英

对 R 包中的函数进行分组

[英]Grouping functions from an R package

语境

我正在开发一个 R 包,其中包含分为 10 个不同主题的 100 多页长的函数。

期望的行为

我希望用户在调用函数时能够考虑到这些主题。

例如,用户不必调用foo() ,而是必须执行以下任一操作

load(theme1) # or whatever would be used to load a subgroup of functions
foo()

或类似的东西

theme1$foo()

我要防止用户做的是直接加载包并调用函数而不考虑主题,即library(package); foo() library(package); foo()

我试过的

我已经使用模块包来完成前一个包中的后一个解决方案,但是这次由于我的函数是如何相互依赖的,该包的已发布版本不能很好地工作(我已经打开了一个关于该主题的GitHub 问题) )。

我还考虑过编写自己的解决方案,也许是一些简单的事情,涉及创建一个sublibrary()函数,该函数一次仅导出几个函数,但我对此sublibrary()

当然,我猜发布 10 个不同的包在技术上也是可行的,但我认为这太笨拙了,无法考虑。

除了使用模块之外,有没有办法实现上述任一功能?

这里可以使用面向对象的编程,其中theme1是一个类或一个从类实例化的对象,与它相关的函数是方法。 这里有许多替代方案,包括 R 参考类(通过?ReferenceClasses更多信息)、 R6 包proto 包R.oo 包和函数范围(通过demo("scoping")更多信息demo("scoping")

例如使用 proto 包:

library(proto)

theme1 <- proto(
  foo = function(.) print("foo"),
  bar = function(.) print("bar")
)

theme1$foo()
## [1] "foo"
theme1$bar()
## [1] "bar"

如果这只是一个分组问题,并且如果您不需要本地存储或继承,那么我们甚至可以使用列表:

theme1 <- list(foo = function() print("foo"),
               bar = function() print("bar"))

theme1$foo()
## [1] "foo"
theme1$bar()
## [1] "bar"

可以使用许多其他 OO 方法,但它们涉及创建一个类,然后使用该类创建单个对象(这是一个额外的步骤); 但是,它们确实支持问题的 $ 语法。

使用 R6 我们有:

library(R6)

Theme1 = R6Class("theme1",
  public = list(
    foo = function() print("foo"),
    bar = function() print("bar")
  )
)

theme1 <- Theme1$new() # generate a Theme1 object

theme1$foo()
## [1] "foo"
theme1$bar()
## [1] "bar"

或使用参考类(不需要包):

setRefClass(
  "Theme1",
  methods = list(
    foo = function() print("foo"),
    bar = function() print("bar")
  )
)

theme1 <- Theme1()  # generate Theme1 object

theme1$foo()
## [1] "foo"
theme1$bar()
## [1] "bar"

或使用函数作用域(不需要包):

Theme1 <- function() list(
  foo = function() print("foo"),
  bar = function() print("bar")
)

theme1 <- Theme1()

theme1$foo()
## [1] "foo"
theme1$bar()
## [1] "bar"

这是如何实现子sublibrary功能的想法。 在这种情况下,我们将使用它来加载ggplot2一小部分

sublibrary <- function(theme) {
  subgroups <- 
    list(basic   = list(ggplot = ggplot2::ggplot,
                        aes = ggplot2::aes,
                        geom_line = ggplot2::geom_line,
                        geom_point = ggplot2::geom_point),
        advanced = list(scale_color_manual = ggplot2::scale_color_manual,
                        theme = ggplot2::theme))
  
  attach(list2env(subgroups[[theme]]))
}

这意味着我可以在不加载整个包的情况下执行以下操作:

sublibrary("basic")

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point()

实际上, subgroup对象将存储在函数外部、包命名空间内的列表或环境中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM