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

时间:2013-03-25 16:52:09

标签: r namespaces search-path

这个问题是对post的一种跟进,因为我仍然不完全相信,就代码的健壮性而言,打字namespace::foo()习惯不会好得多而不只是键入foo()并祈祷你得到所需的结果; - )

实际问题

我知道这严重违反了“标准R约定”,但我们只是说我很好奇;-) 是否有可能以某种方式将临时命名空间附加到搜索路径?


动机

我的包裹mypkg仍在“开发阶段”(即不是真正的R包):

  • 我想将我的功能导入环境mypkg而不是.GlobalEnv
  • 然后将mypkg附加到搜索路径(如果可能,作为真正的命名空间)
  • 以便能够致电mypkg::foo()

我完全清楚调用::有它的缺点(它只需要输入一个函数的名称并让R隐式处理查找所需的时间更长)和/或由于 a) R扫描搜索路径, b)包可以导入其依赖项(即使用“Imports”而不是“Depends”,不导出某些函数等)。但是我已经看到我的代码至少崩溃了两次,因为某些软件包已经覆盖了某些(基本)函数,所以我从“盲目信任”转变为“更好的安全而不是抱歉”模式; - )

我尝试了什么

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的评论:我实际上并不关心附加环境是完全成熟的命名空间还是只是普通环境,只要我可以扩展:: 同时保持“语法延伸” “功能(即能够拨打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实际上不是一个命名空间,而只是某个环境附加到搜索路径,那么它也应该能够做到这一点:

"::*" <- 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 :(得分:0)

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

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

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