Chcę spojrzeć na kod źródłowy funkcji, aby zobaczyć, jak ona działa. Wiem, że mogę wydrukować funkcję, wpisując jej nazwę w wierszu polecenia:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
Co w tym przypadku UseMethod("t")
oznacza? Jak znaleźć kod źródłowy, z którego faktycznie korzysta, na przykład t(1:10)
:?
Czy jest jakaś różnica między tym, kiedy widzę, UseMethod
a kiedy widzę standardGeneric
i showMethods
, jak w przypadku with
?
> with
standardGeneric for "with" defined from package "base"
function (data, expr, ...)
standardGeneric("with")
<bytecode: 0x102fb3fc0>
<environment: 0x102fab988>
Methods may be defined for arguments: data
Use showMethods("with") for currently available ones.
W innych przypadkach widzę, że wywoływane są funkcje R, ale nie mogę znaleźć kodu źródłowego dla tych funkcji.
> ts.union
function (..., dframe = FALSE)
.cbind.ts(list(...), .makeNamesTs(...), dframe = dframe, union = TRUE)
<bytecode: 0x36fbf88>
<environment: namespace:stats>
> .cbindts
Error: object '.cbindts' not found
> .makeNamesTs
Error: object '.makeNamesTs' not found
Jak znaleźć funkcje takie jak .cbindts
i .makeNamesTs
?
W jeszcze innych przypadkach jest trochę kodu R, ale większość pracy wydaje się być wykonywana gdzie indziej.
> matrix
function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
{
if (is.object(data) || !is.atomic(data))
data <- as.vector(data)
.Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow),
missing(ncol)))
}
<bytecode: 0x134bd10>
<environment: namespace:base>
> .Internal
function (call) .Primitive(".Internal")
> .Primitive
function (name) .Primitive(".Primitive")
Jak dowiedzieć się, na czym .Primitive
polega ta funkcja? Podobnie, niektóre funkcje zadzwonić .C
, .Call
, .Fortran
, .External
, lub .Internal
. Jak znaleźć dla nich kod źródłowy?
Odpowiedzi:
UseMethod("t")
mówi ci, żet()
jest to ogólna funkcja ( S3 ), która ma metody dla różnych klas obiektów.System wysyłki metodą S3
W przypadku klas S3 można użyć
methods
funkcji, aby wyświetlić listę metod dla określonej funkcji ogólnej lub klasy.„Niewidoczne funkcje są oznaczone gwiazdką” oznacza, że funkcja nie jest eksportowana z przestrzeni nazw swojego pakietu. Nadal możesz przeglądać jego kod źródłowy za pomocą
:::
funkcji (tj.stats:::t.ts
) Lub za pomocągetAnywhere()
.getAnywhere()
jest przydatne, ponieważ nie musisz wiedzieć, z którego pakietu pochodzi ta funkcja.System wysyłki metody S4
System S4 to nowszy system dyspozytorski i stanowi alternatywę dla systemu S3. Oto przykład funkcji S4:
Dane wyjściowe już oferują wiele informacji.
standardGeneric
jest wskaźnikiem funkcji S4. Pomocna jest metoda wyświetlania zdefiniowanych metod S4:getMethod
można użyć do wyświetlenia kodu źródłowego jednej z metod:Istnieją również metody z bardziej złożonymi podpisami dla każdej metody, na przykład
Aby zobaczyć kod źródłowy jednej z tych metod, należy podać cały podpis, np
Podanie częściowego podpisu nie wystarczy
Funkcje wywołujące funkcje nieobsługiwane
W przypadku
ts.union
,.cbindts
i.makeNamesTs
są unexported funkcje zstats
przestrzeni nazw. Możesz wyświetlić kod źródłowy niewyportowanych funkcji za pomocą:::
operatora lubgetAnywhere
.Funkcje wywołujące skompilowany kod
Zauważ, że „skompilowany” nie odnosi się do skompilowanego bajtowo kodu R utworzonego przez pakiet kompilatora .
<bytecode: 0x294e410>
Linia w powyższym wyjściu wskazuje, że funkcja jest bajt skompilowany, i nadal można zobaczyć źródło z linii poleceń R.Funkcje połączeń
.C
,.Call
,.Fortran
,.External
,.Internal
, lub.Primitive
dzwonisz punkty wejścia w skompilowanego kodu, więc trzeba będzie spojrzeć na źródła skompilowanego kodu, jeśli chcesz, aby w pełni zrozumieć tę funkcję. To lustro GitHub kodu źródłowego R jest przyzwoitym miejscem do rozpoczęcia. Ta funkcjapryr::show_c_source
może być przydatnym narzędziem, ponieważ zabierze Cię bezpośrednio do strony GitHub.Internal
i.Primitive
wywołań. Pakiety mogą korzystać.C
,.Call
,.Fortran
, i.External
; ale nie.Internal
lub.Primitive
, ponieważ są one używane do wywoływania funkcji wbudowanych w interpreter R.Wywołania niektórych z powyższych funkcji mogą wykorzystywać obiekt zamiast ciągu znaków w celu odniesienia do skompilowanej funkcji. W tych przypadkach, obiekt jest klasy
"NativeSymbolInfo"
,"RegisteredNativeSymbol"
lub"NativeSymbol"
; a wydrukowanie obiektu dostarcza użytecznych informacji. Na przykładoptim
połączenia.External2(C_optimhess, res$par, fn1, gr1, con)
(uwaga, żeC_optimhess
nie"C_optimhess"
).optim
znajduje się w pakiecie statystyk, więc możesz wpisać,stats:::C_optimhess
aby wyświetlić informacje o wywołanej kompilowanej funkcji.Skompilowany kod w pakiecie
Jeśli chcesz wyświetlić skompilowany kod w pakiecie, musisz pobrać / rozpakować źródło pakietu. Zainstalowane pliki binarne nie są wystarczające. Kod źródłowy pakietu jest dostępny z tego samego repozytorium CRAN (lub zgodnego z CRAN), z którego pakiet został pierwotnie zainstalowany.
download.packages()
Funkcja może dostać źródła pakietów dla Ciebie.Spowoduje to pobranie źródłowej wersji pakietu Matrix i zapisanie odpowiedniego
.tar.gz
pliku w bieżącym katalogu. Kod źródłowy skompilowanych funkcji można znaleźć wsrc
katalogu nieskompresowanego i nieopartego pliku. Etap rozpakowywania i odznaczania można wykonać poza funkcjąR
lub od wewnątrzR
za pomocą tejuntar()
funkcji. Możliwe jest połączenie kroku pobierania i rozszerzenia w jedno wywołanie (pamiętaj, że tylko jeden pakiet na raz można pobrać i rozpakować w ten sposób):Alternatywnie, jeśli tworzenie pakietu jest hostowane publicznie (np. Przez GitHub , R-Forge lub RForge.net ), prawdopodobnie możesz przeglądać kod źródłowy online.
Skompilowany kod w pakiecie podstawowym
Niektóre pakiety są uważane za pakiety „podstawowe”. Te pakiety dostarczane z R i ich wersja jest zablokowane do wersji R. Przykłady obejmują
base
,compiler
,stats
, iutils
. Jako takie nie są dostępne jako osobne pakiety do pobrania w CRAN, jak opisano powyżej. Są raczej częścią drzewa źródłowego R w poszczególnych katalogach pakietów w/src/library/
. Sposób uzyskania dostępu do źródła R opisano w następnej sekcji.Skompilowany kod wbudowany w interpreter R.
Jeśli chcesz wyświetlić kod wbudowany w interpreter R, musisz pobrać / rozpakować źródła R; lub możesz przeglądać źródła online za pośrednictwem repozytorium R Subversion lub lustra github Winstona Changa .
Artykuł informacyjny R Uwe Liggesa (PDF) (s. 43) stanowi dobre ogólne odniesienie do tego, jak wyświetlić kod źródłowy
.Internal
i.Primitive
funkcje. Podstawowe kroki to najpierw poszukać nazwy funkcji w,src/main/names.c
a następnie poszukać nazwy „C-entry” w plikach wsrc/main/*
.źródło
RStudio
, po naciśnięciuF2
klawisza spróbujesz pobrać źródło funkcji, na której kończy się kursor tekstowy .scale
czyli S3 - dostałemUseMethod("scale")
i wykorzystałemgetAnywhere(scale.default)
). Ale proste funkcje działają dobrze.Oprócz innych odpowiedzi na to pytanie i jego duplikaty, oto dobry sposób na uzyskanie kodu źródłowego dla funkcji pakietu bez konieczności wiedzieć, w którym pakiecie się znajduje. Np. Jeśli chcemy źródła
randomForest::rfcv()
:Aby wyświetlić / edytować w wyskakującym oknie:
Aby przekierować do osobnego pliku :
źródło
View(foo)
; gdziefoo
była funkcja z już załadowanego pakietu.edit()
otwiera edytor tekstu (wybrany przez użytkownika) , podczas gdyView()
otwiera przeglądarkę arkuszy kalkulacyjnych typu Excel dla danych , ta ostatnia jest dobra do przeglądania danych (wielokolumnowych), ale zwykle jest okropna dla kodu innego niż długość zabawki. Na przykład, jak wskazałem, ogólnie pierwszą rzeczą, którą chcę zrobić podczas przeglądania funkcji, jest pominięcie / zwinięcie / obojętne logiki parsowania i domyślnej akcji, aby zobaczyć, co ta funkcja faktycznie robi .Ujawnia się podczas debugowania za pomocą funkcji debug (). Załóżmy, że chcesz zobaczyć podstawowy kod w funkcji transpozycji t (). Samo wpisanie „t” nie ujawnia wiele.
Ale używając „debugowania (functionName)”, ujawnia on podstawowy kod, bez wewnętrznych elementów.
EDYCJA: debugonce () dokonuje tego samego bez konieczności używania undebug ()
źródło
debugonce
zamiastdebug
w tym przypadku.W przypadku funkcji niebędących prymitywnymi podstawa R zawiera funkcję o nazwie,
body()
która zwraca treść funkcji. Na przykład można wyświetlić źródłoprint.Date()
funkcji:wyprodukuje to:
Jeśli pracujesz w skrypcie i chcesz, aby kod funkcji był wektorem znaków, możesz go zdobyć.
dostanie cię:
Dlaczego miałbym chcieć zrobić coś takiego? Tworzyłem niestandardowy obiekt S3 (
x
, gdzieclass(x) = "foo"
) na podstawie listy. Jeden z członków listy (o nazwie „fun”) był funkcją i chciałemprint.foo()
wyświetlić kod źródłowy funkcji z wcięciem. Więc skończyłem z następującym fragmentem kodu wprint.foo()
:który wcina i wyświetla kod związany z
x[["fun"]]
.źródło
Nie widziałem, jak to pasuje do głównej odpowiedzi, ale przez chwilę mnie zaskoczyło, więc dodaję to tutaj:
Infix Operators
Aby zobaczyć kod źródłowy niektórych operatorów infiksowych bazowej (np
%%
,%*%
,%in%
), użyjgetAnywhere
, np:Główna odpowiedź dotyczy tego, jak następnie używać luster do głębszego kopania.
źródło
getAnywhere
. Lub może po prostu użyć odwrócone, pojedyncze apostrofy, jeśli już znasz nazwę operatora:`%in%`
.getAnywhere
jest również wspomniany w twojej odpowiedzi, ale myślę, że konkretne odniesienie do infix jest przydatne do przyszłego odniesienia do tej odpowiedzi - czytałem tę stronę wiele razy i wciąż byłem nieco zakłopotany próbą znalezienia kodu dla takich funkcji dla podczas gdy - i nie sądzę, że pasuje do przepływu żadnej innej odpowiedzi (które są używanegetAnywhere
w innym celu).W języku R jest bardzo przydatna funkcja
edit
Otworzy kod źródłowy
optim
korzystania z edytora określonego w Roptions
, a następnie możesz go edytować i przypisać zmodyfikowaną funkcję donew_optim
. Bardzo podoba mi się ta funkcja do przeglądania kodu lub do debugowania kodu, np. Drukowania niektórych komunikatów lub zmiennych, a nawet przypisywania ich do zmiennych globalnych w celu dalszego badania (oczywiście można użyćdebug
).Jeśli chcesz tylko wyświetlić kod źródłowy i nie chcesz, aby denerwujący długi kod źródłowy został wydrukowany na konsoli, możesz go użyć
Oczywiście nie można tego użyć do przeglądania kodu źródłowego C / C ++ lub Fortran.
BTW,
edit
może otwierać inne obiekty, takie jak lista, macierz itp., Które następnie pokazują strukturę danych z atrybutami. Funkcjide
można użyć do otwarcia edytora podobnego do programu Excel (jeśli GUI go obsługuje), aby zmodyfikować matrycę lub ramkę danych i zwrócić nowy. Jest to czasami przydatne, ale należy tego unikać w zwykłych przypadkach, szczególnie gdy macierz jest duża.źródło
Tak długo, jak funkcja jest napisana w czystym R, a nie w C / C ++ / Fortran, można użyć następujących. W przeciwnym razie najlepszym sposobem jest debugowanie i użycie polecenia „ skok do ”:
źródło
body
.identical(functionBody, body)
jestTRUE
.base::body
imethods::functionBody
chociaż raczej nie zostaną zdemaskowani.body
można też pominąćW RStudio istnieją (co najmniej) 3 sposoby:
View
(nazwa_funkcji) (jak podano powyżej)Otworzy się nowe okienko z kodem źródłowym. Jeśli przejdziesz do .Primitive lub .C będziesz potrzebować innej metody, przepraszam.
źródło
View([function_name])
- np.View(mean)
Upewnij się, że używasz wielkich liter [V]. Kod tylko do odczytu zostanie otwarty w edytorze.źródło
Możesz także spróbować użyć
print.function()
S3, aby uzyskać funkcję zapisu w konsoli.źródło
print.function()
jest metodą S3 . Ogólny toprint()
. I generalnie nie jest dobrym pomysłem wywoływać metody bezpośrednio. To pokonuje cały cel funkcji ogólnych i metody wysyłania.