首页 文章

将临时命名空间附加到搜索路径

提问于
浏览
3

这个问题是对这个post的跟进,因为我输入 namespace::foo() 习惯要好得多,而不是只输入 foo() 并祈祷你得到理想的结果;-)

实际问题

我只是说我很好奇;-) Is it possible to attach a temporary namespace to the search path somehow?


动机

在我的包 mypkg 仍处于“开发阶段”(即 not a true R package yet )的时刻:

  • 我想将我的函数源化为一个环境 mypkg 而不是 .GlobalEnv

  • 然后将 mypkg 附加到搜索路径(如果可能,作为真正的命名空间)

  • 以便能够调用 mypkg::foo()

我完全知道调用 :: 有它的缺点(它只需要输入一个函数的名称并让R隐式处理查找所需的时间更长)和/或可能不被认为是必要的,因为 a) R扫描搜索路径和 b) 包可以导入它们的依赖项(即使用"Imports"而不是"Depends",不导出某些函数等) . 但是我看到我的代码至少崩溃了两次,因为某些包已经覆盖了某些(基本)函数,所以我从"blind trust"转到"better-to-be-safe-than-sorry"模式;-)

我尝试了什么

AFAIU,命名空间原则上只是一些特殊的环境

> search()
[1] ".GlobalEnv"        "package:stats"     "package:graphics" 
[4] "package:grDevices" "package:utils"     "package:datasets" 
[7] "package:methods"   "Autoloads"         "package:base"     

> asNamespace("base")
<environment: namespace:base>

还有 attach() 函数将对象附加到搜索路径 . 所以这就是我的想法:

temp.namespace <- new.env(parent=emptyenv())
attach(temp.namespace)
> asNamespace("temp.namespace")
Error in loadNamespace(name) : 
  there is no package called 'temp.namespace'

我想我不得不使用 attachNamepace() 并在 library() 中调用它之前弄清楚它的预期 . 有任何想法吗?


编辑

关于Hadley 's comment: I actually wouldn't关心附加环境是完全成熟的命名空间还是只是普通环境,只要我能扩展 :: while keeping the "syntactic sugering" feature (即能够调用 pkg::foo() 而不是 "::"(pkg="pkg", name="foo")() ) .

这就是函数 "::" 的样子:

> get("::")
function (pkg, name) 
{
    pkg <- as.character(substitute(pkg))
    name <- as.character(substitute(name))
    getExportedValue(pkg, name)
}

如果R检测到 pkg 实际上是 not 一个命名空间,而只是一些附加到搜索路径的环境,那么它也应该能够做到这一点:

"::*" <- function (pkg, name) 
{
    pkg <- as.character(substitute(pkg))
    name <- as.character(substitute(name))
    paths <- search()
    if (!pkg %in% paths) stop(paste("Invalid namespace environment:", pkg))
    pos <- which(paths == pkg)
    if (length(pos) > 1) stop(paste("Multiple attached envirs:", pkg))
    get(x=name, pos=pos)
}

它有效,但没有语法含糖:

> "::*"(pkg="tempspace", name="foo")
function(x, y) x + y
> "::*"(pkg="tempspace", name="foo")(x=1, y=2)
[1] 3

我怎么能够调用 pkg::*foo(x=1, y=2) (无视 ::* 是一个非常糟糕的函数名称的事实;-))?

1 回答

  • 0

    你的动机有些不对劲:你的命名空间不必附加到搜索路径以便使用'::'符号,实际上是相反的 .

    搜索路径允许通过查看附加到搜索路径的所有名称空间来选择符号 .

    所以,正如Hadley告诉你的那样,你只需要使用devtools :: load_all(),这就是全部...

相关问题