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 回実行した場合 (たとえば、その間に R を再起動せずに 2 回実行したスクリプトの先頭にある場合)、2 回目original.sub_extは実際ではnew.sub_extなく前 knitr:::sub_extものであるため、無限になります。再帰。

sub_ext内部関数であるため(直接呼び出すことはしませんが、knitr の関数はknitすべて内部的に呼び出します)、呼び出すすべての関数を手動でsub_ext呼び出すように変更することは期待できません。new.sub_extパッケージの名前空間。

4

1 に答える 1

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引数を使用して、トレースする関数の名前空間を共有する他の (エクスポートされた) 関数の名前を渡すことに注意してください。したがって、Knitrの名前空間でエクスポートされていない関数をトレースするには、次のように設定できます。where=knit

于 2013-05-10T03:08:20.790 に答える