3

この質問は、この投稿のフォローアップのようなものです。コードの堅牢性に関しては、入力して目的の結果が得られることを祈るよりも、入力をnamespace::foo()習慣化する方がはるかに良いとはまだ確信していないためです。 foo()-)

実際の質問

これが「標準の R 規則」に大きく反することは承知していますが、ちょっと興味があるとだけ言っておきましょう ;-)一時的な名前空間を何らかの方法で検索パスにアタッチすることは可能ですか?


動機

mypkg私のパッケージがまだ「開発段階」にある時点で(つまり、まだ真の R パッケージではありません):

  • mypkg代わりに環境に関数をソースしたい.GlobalEnv
  • 次に、検索パスにアタッチmypkgします (可能であれば真の名前空間として)
  • 電話できるようにするためにmypkg::foo()

呼び出し::には欠点があることを完全に認識しています (単純に関数の名前を入力して R にルックアップを暗黙的に処理させるよりも時間がかかります)、および/またはa) R が検索パスをスキャンし、b )パッケージは依存関係をインポートできます (つまり、「依存」の代わりに「インポート」を使用する、特定の機能をエクスポートしないなど)。しかし、一部のパッケージが特定の (基本) 関数を上書きしたためにコードがクラッシュするのを少なくとも 2 回見たことがあります。 -)

私が試したこと

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()ます。何か案は?


編集

:: ハドリーのコメントに関して: 私は実際には、接続された環境が完全に成長した名前空間であるか、単に「構文シュガーリング」機能を維持しながら拡張できる限り、単なる通常の環境であるかは気にしません(つまり、pkg::foo()代わりに呼び出すことができます"::"(pkg="pkg", name="foo")()) .

関数"::"は次のようになります。

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

pkgこれは、実際には名前空間ではなく、検索パスに接続された環境であるとR が検出した場合にも実行できるはずです。

"::*" <- 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)(関数の本当に悪い名前であるという事実を無視して::*;-))?

4

1 に答える 1