niszetの日記

細かい情報を載せていくブログ

(R) Viewの挙動を追ってみる (2回目)

なんだかんだでRStudio IDEのソース読んでるだけなんだなー…

さて、RStudio IDE によって乗っ取られているView()ですが、オリジナル版を使うのであればutils::View()のように、パッケージ名を指定してロード1してあげればよいです

hookはどこじゃ…?

さて、このRSrudioによって上書きされているView()の中身の記述をコピペし、別の関数として定義してもうまく動きません。下記のコードは実行するとデバッグモードに入ってしまうのでコピペ実行されないように###エスケープしておきます

### a <- edit(View)
###a
#> function (...) 
#> .rs.callAs(name, hook, original, ...)
#> <environment: 0x0000000016e140e0>
###a()
#> Error in Error in cat("Error in ", name, " : ", e$message, "\n", sep = "") : 
#>   argument 2 (type 'closure') cannot be handled by 'cat'
#> Called from: cat("Error in ", name, " : ", e$message, "\n", sep = "")

とりあえずnameとか(ここには書いていないものの、hookも)ないよってことで。

改めて親環境を丁寧に見ていく

ちょっと1つ上の親環境を見てみます。

View(rlang::env_parent(environment(View)))

f:id:niszet:20180307000328p:plain

おっ!?なんかnameもhookもいますね。このうち、hookを見たいなと思えば

View(rlang::env_parent(environment(View))$hook)

で見てみることができます。出力は省略します(長いので)

置き換えられた関数をどのようにして探すのか

さて、前回列挙した、RStudioによって置き換えられてしまった関数ですが、registerReplaceHookで検索しています。
検索したときの表示はこんな感じ。

github.com

ここに至るまでには何ステップかありました。順に列挙すると、次の通り。

先のhookのところにhookFactoryというかなり意味深な単語があるため、これで検索します。

github.com

すると、.rs.addFunction()という関数が見つかります。今度はこれを検索します

github.com

直前のコメントから、# add a function to the tools:rstudio environmentということで、こいつが関数をtools:rstudio環境に登録するための関数であることがわかりました。

この関数は

assign( envir = .rs.Env, ".rs.addFunction", function(
   name, FN, attrs = list())
{ 
   fullName = paste(".rs.", name, sep="")
   for (attrib in names(attrs))
     attr(FN, attrib) <- attrs[[attrib]]
   assign(fullName, FN, .rs.Env)
   environment(.rs.Env[[fullName]]) <- .rs.Env
})

とあるように、関数名の先頭に.rsをつけて登録するようですね。

この関数によって、先に書いた関数、

# replacing an internal R function
.rs.addFunction( "registerReplaceHook", function(name, package, hook, keepOriginal, namespace = FALSE)
{
   hookFactory <- function(original) function(...) .rs.callAs(name,
                                                             hook, 
                                                             original,
                                                             ...);
   .rs.registerHook(name, package, hookFactory, namespace);
})

が登録されるというところまで追えました。引数にhookとかありますね。

長くなってきたので一旦ここまで。続きをやるかは不明です。

Enjoy!!


  1. library()require()で呼ぶのはattach、::で呼ぶのはloadってAdvancedR 2ndに書かれていたので一応意識して書いてみた。