代码之家  ›  专栏  ›  技术社区  ›  Noah

如何在R包中使用get0只在包名称空间中搜索?

  •  1
  • Noah  · 技术社区  · 5 年前

    假设我的包中有一个内部函数,称之为 is_() ,如果 is() 。尤其是,它会搜索专门的函数,这些函数用于判断提供的对象是否是给定的类。例如 是()吗 可编程为:

    is_ <- function(obj, class) {
      if (exists(paste0("is.", class))) {
         get0(paste0("is.", class))(obj)
      }
      else inherits(obj, class)
    }
    

    这样,如果我在包中进行参数检查,我可以运行以下操作

    is_(x, "numeric_vector")
    

    在我定义的地方

    is.numeric_vector <- function(x) is.numeric(x) && is.null(dim(x))
    

    在我的包裹里。

    is.numeric_vector() 在我的包之外定义,例如,由用户加载的另一个包定义。那样的话 exists() get0() 两者都可以在任何地方找到函数,但我想将搜索限制在包中定义并包含在包名称空间中的函数(即所有导入的包)。这个 envir inherits 争论似乎达到了我想要的目的,但我不知道如何提供它们来获得我想要的结果。我该如何限制 get0() 只在我的包的命名空间中搜索它的参数?

    0 回复  |  直到 5 年前
        1
  •  1
  •   MrFlick    5 年前

    问题是,您的包名称空间将从从全局环境继承的基本名称空间继承。有关更详细的说明,请参见此处: https://adv-r.hadley.nz/environments.html#namespaces .如果你想更多地控制符号查找,你需要自己完成这项工作。你可以包括你自己的 get 在你的软件包中的功能

    # These are private helpers that do not need to be exported from your package.
    .pkgenv <- environment()
    get1 <- function(name, env = .pkgenv) {
      if (identical(env, emptyenv())) {
        NULL
      } else if (identical(env, globalenv())) {
        # stop at global env
        NULL
      } else if (exists(name, envir=env, inherits = FALSE)) {
        env[[name]]
      } else {
        # try parent
        get1(name, parent.env(env))
      }
    }
    

    这将在环境中递归搜索符号,但在全局环境中停止。你可以把它和你的 is_ 功能类似

    is_ <- function(obj, class) {
      if (!is.null(fn <- get1(paste0("is.", class)))) {
        fn(obj)
      } else {
        inherits(obj, class)
      }
    }
    

    这里我们只检查null,而不是单独验证名称,然后检索值。如果 get1 将被称为一堆,你可能想考虑缓存结果,这样你就不必总是继承继承树。

    推荐文章