将临时名称空间附加到搜索路径 [英] Attaching a temporary namespace to the search path

查看:80
本文介绍了将临时名称空间附加到搜索路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该问题是对该 post ,因为我仍然没有完全相信,就代码健壮性而言,养成键入namespace::foo()习惯而不是仅仅键入foo()并祈祷您获得期望的结果并没有更好的选择;-)

This question is sort of a follow up to this post as I'm still not fully convinced that, with respect to code robustness, it wouldn't be far better to make typing namespace::foo() habit instead of just typing foo() and praying you get the desired result ;-)

我知道这在很大程度上违反了标准R约定",但我只是好奇;-) 是否可以将临时名称空间以某种方式附加到搜索路径上?

I'm aware that this goes heavily against "standard R conventions", but let's just say I'm curious ;-) Is it possible to attach a temporary namespace to the search path somehow?

在我的软件包mypkg仍处于"开发阶段"阶段(即还不是真正的R软件包):

At a point where my package mypkg is still in "devel stage" (i.e. not a true R package yet):

  • 我想将我的函数提供给环境mypkg而不是.GlobalEnv
  • 然后将mypkg附加到搜索路径(如果可能,使用真实名称空间)
  • 以便能够拨打mypkg::foo()
  • I'd like to source my functions into an environment mypkg instead of .GlobalEnv
  • then attach mypkg to the search path (as a true namespace if possible)
  • in order to be able to call mypkg::foo()

我非常清楚,调用::有其缺点(比简单地键入一个函数的名称并让R隐式地处理查找要花费更长的时间)和/或由于 a的方式可能被认为是不必要的) R通过搜索路径进行扫描,并且 b)包可能会导入其依赖项(即,使用导入"代替"Depends",而不导出某些功能等).但是我已经看到我的代码至少崩溃了两次,原因是某些软件包已经覆盖了某些(基本)功能,因此我从盲目信任"模式转到优于安全模式". -)

I'm perfectly aware that calling :: has its downsides (it takes longer than simply typing a function's name and letting R handle the lookup implicitly) and/or might not be considered necessary due to the way a) R scans through the search path and b) packages may import their dependencies (i.e. using "Imports" instead of "Depends", not exporting certain functions etc). But I've seen my code crash at least twice due to the fact that some package has overwritten certain (base) functions, so I went from "blind trust" to "better-to-be-safe-than-sorry" mode ;-)

AFAIU,名称空间原则上不过是某种特殊的环境

AFAIU, namespaces are in principle nothing more than some special kind of environment

> 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()函数,将对象附加到搜索路径.所以这就是我的想法:

And there's the attach() function that attaches objects to the search path. So here's what I thought:

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()中被调用之前的期望.有什么想法吗?

I guess I somehow have to work with attachNamepace() and figure out what this expects before it is called in in library(). Any ideas?

关于Hadley的评论:实际上,我不介意附加环境是完整的名称空间还是只是普通环境,只要我可以扩展:: 并同时保持语法修饰"功能即可. (即能够呼叫pkg::foo()而不是"::"(pkg="pkg", name="foo")()).

With respect to Hadley's comment: I actually wouldn't care whether the attached environment is a full-grown namespace or just an ordinary environment as long as I could extend :: while keeping the "syntactic sugering" feature (i.e. being able to call pkg::foo() instead of "::"(pkg="pkg", name="foo")()).

这是函数"::"的外观:

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

如果R检测到pkg实际上不是命名空间,而只是连接到搜索路径的某些环境,这也是应该做的:

This is what it should also be able to do in case R detects that pkg is in fact not a namespace but just some environment attached to the search path:

"::*" <- 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)
}

它有效,但是没有语法加糖功能:

It works, but there's no syntactic sugaring:

> "::*"(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)(忽略::*是一个函数的真坏名称的事实;-))?

How would I be able to call pkg::*foo(x=1, y=2) (disregarding the fact that ::* is a really bad name for a function ;-))?

推荐答案

您的动机有误:为了使用'::'标记,不必将名称空间附加到搜索路径中,它是实际上是相反的.

There is something wrong in your motivation: your namespace does NOT have to be attached to the search path in order to use the '::' notation, it is actually the opposite.

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

The search path allows symbols to be picked by looking at all namespaces attached to the search path.

所以,正如Hadley告诉您的那样,您只需要使用devtools :: load_all(),就可以了.

So, as Hadley told you, you just have to use devtools::load_all(), that's all...

这篇关于将临时名称空间附加到搜索路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆