2014-10-30 16 views
9

Używam pakietu R, w którym są 2 funkcje f1 i f2 (z f2 calling f1)
Chcę zastąpić funkcję f1.R: Jaki jest właściwy sposób nadpisywania funkcji z paczki?

Od wersji 2.15 i obowiązkowego użycia przestrzeni nazw w pakietach, jeśli po prostu otrzymuję nową funkcję, jest ona faktycznie dostępna w środowisku globalnym (tj. Samo wywołanie f1 (x) w konsoli zwraca nowy wynik). Jednak wywołanie f2 nadal będzie używać zapakowanej funkcji f1. (Ponieważ przestrzeń nazw modyfikuje ścieżkę przeszukiwania i zamyka ją zgodnie z wytłumaczonym opisem: here in the Writing R Extensions samouczek)
Jaki jest właściwy sposób całkowitego zastąpienia f1 nowym? (oprócz budowania ponownie pakietu!) Może to być przydatne w kilku sytuacjach. Na przykład, jeśli istnieje błąd w pakiecie, który nie został opracowany. Lub jeśli nie chcesz ponownie budować pakietów codziennie, gdy są jeszcze w fazie rozwoju.

wiem o funkcji

assignInNamespace("f1",f1,ns="mypackage") 

Jednak strona pomocy ?assignInNamespace jest nieco enignmatic i wydaje się zniechęcać ludzi od używania go bez podania więcej informacji, i nie mogłem znaleźć żadnych rekomendacji najlepszych praktyk na oficjalny tutorial CRAN. i po wywołaniu tej funkcji:

# Any of these 2 calls return the new function 
mypackage::f1 
getFromNamespace(x = "f1", envir = as.environment("package:mypackage")) 

# while this one still returns the old packaged version 
getFunction(name = "f1", where = as.environment("package:mypackage")) 

To bardzo niepokojące. Jak wpływa na to ścieżka wyszukiwania?

Na razie robię jakieś brzydkie rzeczy, takich jak modyfikowanie funkcji lockEnvironment tak że library nie blokuje nazw pakietów, i mogę zablokować ją w późniejszym etapie raz Wymieniłem F1 (co nie wydaje się naprawdę dobry praktyki)

Więc w zasadzie mam 2 pytania:

  1. co to dokładnie assignInNamespace w przypadku nazw pakietu (który ma zostać zablokowany)
  2. Jakie są dobre praktyki?

wielkie dzięki za podzielenie się z Państwem swoim doświadczeniem.

EDYCJA: osoby zainteresowane tym pytaniem mogą uznać obiekt this blog post za bardzo interesujący.

+1

Świetne pytanie. Ostatnio szukałem wyjaśnienia, znalazłem [stary wątek] (https://stat.ethz.ch/pipermail/r-help/2008-August/171217.html) na temat, który wydaje się być odpowiedni . – tonytonov

+0

@tonytonov Dzięki za twój link. Nie udało mi się zrozumieć, co robił "unlockBinding" w przypadku pakietu. Wydaje się, że robienie właśnie 'assignInNamespace' ma dokładnie taki sam wynik. Jakaś wskazówka? – RockScience

+0

Niezupełnie. Zgodnie z moim doświadczeniem 'assignInNamespace' działa lub nie działa w zależności od pakietu i nie mam pojęcia, dlaczego tak się dzieje. Jeśli się nie powiedzie, to rozwiązanie obejmujące 'unlockBinding' również nie działa. – tonytonov

Odpowiedz

3

Istnieje wiele różnych przypadków tutaj.

Jeśli jest to błąd w pakiecie cudzego
Wtedy najlepszym rozwiązaniem jest kontakt z opiekunem pakietu i przekonać ich, aby go naprawić. W ten sposób wszyscy dostaną poprawkę, nie tylko ty.

Jeśli jest to błąd rozwijając swój własny pakiet
Następnie trzeba znaleźć obieg gdzie pakiety przebudowa jest łatwe. Podobnie jak przy korzystaniu z pakietu devtools i pisaniu build(mypackage) lub kliknięciu przycisku ("Utwórz ponownie: & Załaduj ponownie" w RStudio; "Kompilacja R CMD" w Architect).

Jeśli chcesz po prostu różne zachowanie do istniejącego pakietu
Jeśli to nie jest błąd jako takie lub opiekun pakietu nie będzie poprawki, które chcesz, a następnie trzeba będzie utrzymywać was własna kopia f1. Użycie numeru assignInNamespace do nadpisania go w istniejącym pakiecie jest OK do eksploracji, ale jest trochę hackowskie, więc nie nadaje się na stałe rozwiązanie.

Najlepiej jest utworzyć własny pakiet zawierający kopie f1 i f2. To mniej wysiłku, niż się wydaje, ponieważ możesz po prostu zdefiniować f2 <- existingpackage::f2.


W odpowiedzi na komentarz:

Drugiej i przypadków trzecich sens, jeśli jesteś sam, ale wymagają one, aby zbudować i zainstalować pakiety, które jest trudne w przypadku mojej organizacji jako pakietach są wdrażane na kilkudziesięciu komputerach i potrzebuję uprawnień administratora do aktualizacji pakietów.

Weź więc kopię istniejącego źródła pakietu, zainstaluj poprawkę i umieść ją w sieci firmowej lub github lub Bitbucket. Następnie zaktualizowany pakiet można zainstalować programowo poprzez

install.packages("//some/network/path/mypackage_0.0-1.tar.gz", repos = NULL) 

lub

library(devtools) 
install_github("mypackage", "mygithubusername") 

Ponieważ instalacja jest tylko linia kodu, można łatwo przesunąć go do jak największej liczby maszyn, jak chcesz. Nie potrzebujesz również dostępu do roota - wystarczy zainstalować pakiet w folderze biblioteki, który nie wymaga dostępu root'a do zapisu. (Przeczytaj strony pomocy Startup i .libPaths, aby dowiedzieć się, jak zdefiniować nową bibliotekę.) Będziesz potrzebować dostępu do tych komputerów, ale nic na to nie poradzę. Porozmawiaj z administratorem sieci, swoim szefem lub kimkolwiek, kto może uzyskać pozwolenie.

+1

zgodził się na wszystkie te punkty, ale wszystko to działa, jeśli masz czas. ** Pierwszy przypadek ** jest rzeczywiście najlepszą praktyką, ale najpierw muszę to naprawić, ponieważ ustalenie go w CRAN przez właściciela pakietu może zająć tygodnie. ** Drugi i trzeci przypadek ** ma sens, jeśli jesteś sam, ale wymagają one zbudowania i zainstalowania pakietów, co jest trudne w przypadku mojej organizacji, ponieważ pakiety są wdrażane na kilkudziesięciu komputerach i potrzebuję uprawnień administratora do aktualizacji pakietów . Niestety uważam, że R nie był przeznaczony dla osób, które się spieszą. – RockScience

Powiązane problemy