这个问题是对这个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 回答
你的动机有些不对劲:你的命名空间不必附加到搜索路径以便使用'::'符号,实际上是相反的 .
搜索路径允许通过查看附加到搜索路径的所有名称空间来选择符号 .
所以,正如Hadley告诉你的那样,你只需要使用devtools :: load_all(),这就是全部...