r - retrieve original version of package function even if over-assigned -
suppose replace function of package, example knitr:::sub_ext. (note: i'm particularly interested internal function, i.e. accessible ::: opposed ::, same answer may work both).
library(knitr) my.sub_ext <- function (x, ext) { return("i'm in package stealing functions d:") } # replace knitr:::sub_ext my.sub_ext knitr <- asnamespace('knitr') unlockbinding('sub_ext', knitr) assign('sub_ext', my.sub_ext, knitr) lockbinding('sub_ext', knitr) question: there way retrieve original knitr:::sub_ext after i've done this? preferably without reloading package?
(i know people want know why want here is. not required reading question). i've been patching functions in packages (not sub_ext function...):
original.sub_ext <- knitr:::sub_ext new.sub_ext <- function (x, ext) { # code first, e.g. x <- do.something.with(x) # call original knitr:::sub_ext original.sub_ext(x, ext) } # set knitr:::sub_ext new.sub_ext before. i agree not in general idea (in cases these quick fixes until changes make way cran, or "feature requests" never approved because case-specific).
the problem above if accidentally execute twice (e.g. it's @ top of script run twice without restarting r in between), on second time original.sub_ext previous new.sub_ext opposed real knitr:::sub_ext, infinite recursion.
since sub_ext internal function (i wouldn't call directly, functions knitr knit call internally), can't hope modify functions call sub_ext call new.sub_ext manually, hence approach of replacing definition in package namespace.
when assign('sub_ext', my.sub_ext, knitr), irrevocably overwriting value associated sub_ext value of my.sub_ext. if first stash original value, though, it's not hard reset when you're done:
library(knitr) knitr <- asnamespace("knitr") ## store original value of sub_ext .sub_ext <- get("sub_ext", envir = knitr) ## overwrite own function my.sub_ext <- function (x, ext) "i'm in package stealing functions d:" assigninnamespace('sub_ext', my.sub_ext, knitr) knitr:::sub_ext("eg.csv", "pdf") # [1] "i'm in package stealing functions d:" ## reset when you're done assigninnamespace('sub_ext', .sub_ext, knitr) knitr:::sub_ext("eg.csv", "pdf") # [1] "eg.pdf" alternatively, long adding lines of code what's there, add code using trace(). what's nice trace() that, when done, can use untrace() revert function's body original form:
trace(what = "mean.default", tracer = quote({ <- 1 b <- 2 x <- x*(a+b) }), @ = 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 note if function tracing in namespace, you'll want use trace()'s where argument, passing name of other (exported) function shares to-be-traced function's namespace. so, trace unexported function in knitr's namespace, set where=knit
Comments
Post a Comment