2013-05-10 17 views
6

Paket işlevinin orijinal sürümünü alsa bile, paketin bir işlevini değiştirdiğimi varsayalım, örneğin knitr:::sub_ext. (Not: Özelliklenumaralı işlevinin bulunduğu, ancak ::'un aksine ::: tarafından erişilebildiğiyle özellikle ilgileniyorum, ancak aynı yanıt her ikisi için de geçerli olabilir)., over-assign

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) 

Soru: Bunu yaptıktan sonra orijinalknitr:::sub_ext almak için herhangi bir yolu var mı? Tercihen paketi yeniden yüklemeden mi?


(Bazı insanlar bunu. Soru için okunması gerekli edilmedi işte bunu yapmak isteyeyim neden bilmek istiyorum biliyorum). Ben (... aslında sub_ext fonksiyonu) şöyle ambalajlarda bazı fonksiyonlarını yama oldum:

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. 

Ben değişiklikler yapana kadar çoğu durumda bu hızlı düzeltmeleri vardır (bu genel iyi bir fikir değil katılıyorum CRAN'a doğru yol alırlar ya da bir şekilde onaylanmış olan "özellik istekleri" olurlar.

yanlışlıkla iki kez çalıştırmak eğer yukarıdaki sorun (örneğin ben aradaki R yeniden başlatmadan iki kez çalıştırılan bir komut üst kısmında) karşıt olarak original.sub_ext aslında önceki new.sub_ext ikinci zamanında, gerçekknitr:::sub_ext, bu yüzden sonsuz yineleme olsun. sub_ext yana

bir fonksiyonu (doğrudan demezdim, ama knit gibi knitr gelen işlevler tüm dahili diyoruz), el new.sub_ext aramaya sub_ext çağrı tüm fonksiyonları değiştirmek için umut olamaz Bu nedenle, tanımın paket ad alanında değiştirilmesi yaklaşımı.

cevap

4

assign('sub_ext', my.sub_ext, knitr)'u yaptığınızda, my.sub_ext değeriyle daha önce sub_ext ile ilişkilendirilmiş olan değerin geri alınamaz bir şekilde üzerine yazılır. öncelikle orijinal değerini saklamak Eğer bitince, yine de, onu sıfırlamak için zor değil:

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" 

Alternatif, sürece sadece zaten olan, yapabilirsin kod satırlarından ekliyoruz olarak trace() kullanarak bu kodu ekleyin. Eğer inceliyoruz işlevi ad alanında ise

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 

Not

, istediğiniz edeceğiz: Ne trace() hakkında güzel işiniz bittiğinde, sen orijinal haline işlevin vücudunu dönmek için untrace() kullanabilirsiniz, yani trace() 'un where argümanını kullanmak için, izlenen işlevin ad alanını paylaşan diğer (dışa aktarılmış) işlevin adını aktarır. Yani, knitr 'un ad alanında bir dışa aktarılmamış işlevi izlemek için where=knit

+0

AHh'yi ayarlayabilirsiniz, şüphesiz ben (değerinin geri alınamaz bir şekilde üzerine yazılıyor). Özel/"taze" bir ortamda 'knitr' yi yeniden yüklemek gibi bir şey yapmasını ve oradan değeri almasını umuyordum. Ancak, bittiğimde değeri sıfırlamaktan son derece mutluyum (neden bunu düşünmedim ?!) ve soruya ilham veren durum aslında mevcut fonksiyona kod satırlarının eklenmesi durumundadır, bu yüzden 'trace' yöntemini bile kullanabilirim (güzel btw! daha önce hiç' trace' kullanılmamıştır). –

+0

@ mathematical.coffee - Sanırım her zaman böyle bir şey yapabilirsiniz, fonksiyonun tanımını taze bir R oturumundan almak için bir sistem çağrısı kullanın: 'x <- system2 (" Rscript ", c (" - e ", shQuote) ('dput (knitr ::: sub_ext)')), stdout = TRUE); xx <- kaynak (textConnection (x)) $ değer; çevre (xx) <- asNamespace ("knitr"); assignInNamespace ("sub_ext", xx, asNamespace ("knitr")). Ama bu oldukça gülünç görünmeye başlar, değil mi? –

+0

Beni 'trace' ile tanıştırdığınız için teşekkürler! – isomorphismes