这个问题是这个问题的后续post因为我仍然不完全相信,就代码的鲁棒性而言,打字不会更好namespace::foo()
习惯而不仅仅是打字foo()
并祈祷你能得到想要的结果;-)
实际问题
我知道这严重违反了“标准 R 约定”,但我们只能说我很好奇;-)是否可以以某种方式将临时名称空间附加到搜索路径?
动机
当我的包裹mypkg
仍处于“发展阶段" (i.e. 还不是真正的 R 包):
- 我想将我的函数引入到一个环境中
mypkg
代替.GlobalEnv
- 然后附加
mypkg
到搜索路径(如果可能的话作为真正的命名空间)
- 为了能够打电话
mypkg::foo()
我完全知道打电话::
有它的缺点(它比简单地输入函数名称并让 R 隐式处理查找需要更长的时间)和/或由于方式可能不被认为是必要的a)R 扫描搜索路径并b)包可以导入它们的依赖项(即使用“导入”而不是“依赖”,不导出某些函数等)。但我已经看到我的代码崩溃了至少两次,因为某些包覆盖了某些(基本)函数,所以我从“盲目信任”转向“安全总比抱歉更好”模式; -)
我尝试过的
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()
。有任何想法吗?
EDIT
关于哈德利的评论:我实际上并不关心附加环境是一个成熟的命名空间还是只是一个普通的环境,只要我可以扩展::
同时保留“语法检查”功能(即能够调用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)
(忽略以下事实:::*
对于一个函数来说是一个非常糟糕的名字;-))?