2013-05-10 4 views
6

パッケージの機能を置き換えるとします(例:knitr:::sub_ext)。 (注:私は特に内部の機能に興味があります。つまり、::ではなく:::でしかアクセスできませんが、同じ回答が両方で機能する場合があります)。余分に割り当てられていても、元のバージョンのパッケージ機能を取得します

library(knitr) 
my.sub_ext <- function (x, ext) { 
    return("I'm in your package stealing your functions D:") 
} 
# replace knitr:::sub_ext with my.sub_ext 
knitr <- asNamespace('knitr') 
unlockBinding('sub_ext', knitr) 
assign('sub_ext', my.sub_ext, knitr) 
lockBinding('sub_ext', knitr) 

質問:私はこれをやった後knitr:::sub_extを取得する方法はありますか?パッケージを再ロードしないことをお勧めしますか?


は(私は何人かの人々は、私はそれは。質問のための読書は必要ありませんので、ここでこれを実行したいと思う理由を知りたい知っています)。私は(...ではない実際にsub_ext機能)ので、のようなパッケージでいくつかの機能にパッチを適用してきた:

original.sub_ext <- knitr:::sub_ext 
new.sub_ext <- function (x, ext) { 
    # some extra code that does something first, e.g. 
    x <- do.something.with(x) 
    # now call the original knitr:::sub_ext 
    original.sub_ext(x, ext) 
} 
# now set knitr:::sub_ext to new.sub_ext like before. 

私は、これは一般的には良いアイデアではありません同意する(変更が作るまでは、ほとんどの場合、これらは迅速な修正されていますCRANに向かう途中であるか、あるいは、彼らがやや特殊なケースであるために決して承認されない「機能要求」である)。

上記の問題は、間違って2回実行した場合です(たとえば、スクリプトの最上部にあり、2度実行しないとRを再開せずに)、2回目にoriginal.sub_extが実際には前のnew.sub_extknitr:::sub_ext、私は無限の再帰を得ます。 sub_ext以来

は(私はそれを直接呼び出すことはありませんが、knitようknitrからの機能はすべて、内部でそれを呼び出す)内部機能ですが、私は手動でnew.sub_extを呼び出すためにsub_extを呼び出して、すべての機能を変更することを期待することはできませんパッケージネームスペースの定義を置き換えるアプローチです。

答えて

4

assign('sub_ext', my.sub_ext, knitr)を実行すると、以前にsub_extに関連付けられた値をmy.sub_extの値で上書きできます。あなたが最初に元の値を隠しておく場合は、しかし、それはあなたが完了したら、それをリセットすることは難しいことではありません。

library(knitr) 
knitr <- asNamespace("knitr") 

## Store the original value of sub_ext 
.sub_ext <- get("sub_ext", envir = knitr) 

## Overwrite it with your own function 
my.sub_ext <- function (x, ext) "I'm in your package stealing your functions D:" 
assignInNamespace('sub_ext', my.sub_ext, knitr) 
knitr:::sub_ext("eg.csv", "pdf") 
# [1] "I'm in your package stealing your functions D:" 

## Reset when you're done 
assignInNamespace('sub_ext', .sub_ext, knitr) 
knitr:::sub_ext("eg.csv", "pdf") 
# [1] "eg.pdf" 

また、限り、あなたはちょうどあなたが、すでにそこに何のコードの行を可能性が追加されますtrace()を使用してそのコードを追加してください。どのような素敵な程度trace()のは、作業が完了したとき、あなたは元の形に関数の体を元に戻すuntrace()を使用することができ、ということである:

trace(what = "mean.default", 
     tracer = quote({ 
      a <- 1 
      b <- 2 
      x <- x*(a+b) 
     }), 
     at = 1) 
mean(1:2) 
# Tracing mean.default(1:2) step 1 
# [1] 4.5 
untrace("mean.default") 
# Untracing function "mean.default" in package "base" 
mean(1:2) 
# [1] 1.5 

注意あなたがトレースしている機能は、名前空間内にある場合、あなたがたいと思うことtrace()where引数を使用するには、トレース対象の関数の名前空間を共有する他の(エクスポートされた)関数の名前を渡します。だから、ニットののネームスペースで、未知の関数をトレースするには、where=knit

+0

を設定することができました。私は(値を取り返しのつかないほど上書きする)ものと思われました。私は個人的な/ "新鮮な"環境でリロード 'knitr'のような何かをすることができ、そこから価値を得ることができると期待していた。しかし、私が完了したら、私は値をリセットすることができてとても満足しています(なぜ私はそれを考えなかったのですか?))、その質問に影響を与えたケースは実際には既存の関数にコードの行を追加する場合であるため、 'trace'メソッドを使用することもできます(nice btw!以前は' trace'を使ったことはありません)。 –

+0

@ mathematical.coffee - 新鮮なRセッションから関数の定義を取り出すためのシステムコールを使って、いつもこういうことができると思います: 'x < - system2(" Rscript "、c(" - e "、shQuote ( 'dput(knitr ::: sub_ext)'))、stdout = TRUE); xx < - source(textConnection(x))$ value;環境(xx)< - asNamespace( "knitr"); assignInNamespace( "sub_ext"、xx、asNamespace( "knitr")) '。しかし、それはかなりばかばかしいように見えますね。 –

+0

私を 'trace'に紹介してくれてありがとう! – isomorphismes

関連する問題