Jak mogę wyświetlić kod źródłowy funkcji?
Chcę spojrzeć na kod źródłowy funkcji, aby zobaczyć, jak to działa. Wiem, że mogę wydrukować funkcję wpisując jej nazwę w wierszu polecenia:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
W tym przypadku, co oznacza UseMethod("t")
? Jak znaleźć kod źródłowy, który jest faktycznie używany przez, na przykład: t(1:10)
?
Czy jest różnica między Kiedy widzę UseMethod
a kiedy widzę standardGeneric
i showMethods
, jak z 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 funkcje R są wywoływane, ale nie mogę znaleźć źródła kod 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 sprawdzić, co robi funkcja .Primitive
? Podobnie niektóre funkcje wywołują .C
, .Call
, .Fortran
, .External
, lub .Internal
. Jak mogę znaleźć dla nich kod źródłowy?
9 answers
UseMethod("t")
mówi, że t()
jest (S3) funkcją ogólną, która ma metody dla różnych klas obiektów.
System wysyłki metody S3
Dla klas S3, możesz użyć funkcji methods
, aby wyświetlić listę metod dla konkretnej ogólnej funkcji lub klasy.
> methods(t)
[1] t.data.frame t.default t.ts*
Non-visible functions are asterisked
> methods(class="ts")
[1] aggregate.ts as.data.frame.ts cbind.ts* cycle.ts*
[5] diffinv.ts* diff.ts kernapply.ts* lines.ts
[9] monthplot.ts* na.omit.ts* Ops.ts* plot.ts
[13] print.ts time.ts* [<-.ts* [.ts*
[17] t.ts* window<-.ts* window.ts*
Non-visible functions are asterisked
"funkcje niewidoczne są oznaczone gwiazdką" oznacza, że funkcja nie jest eksportowana z przestrzeni nazw pakietu. Nadal możesz wyświetlić 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.
> getAnywhere(t.ts)
A single object matching ‘t.ts’ was found
It was found in the following places
registered S3 method for t from namespace stats
namespace:stats
with value
function (x)
{
cl <- oldClass(x)
other <- !(cl %in% c("ts", "mts"))
class(x) <- if (any(other))
cl[other]
attr(x, "tsp") <- NULL
t(x)
}
<bytecode: 0x294e410>
<environment: namespace:stats>
System wysyłki metody S4
System S4 jest nowszym systemem wysyłania metod i jest alternatywą dla systemu S3. Oto przykład funkcji S4:
> library(Matrix)
Loading required package: lattice
> chol2inv
standardGeneric for "chol2inv" defined from package "base"
function (x, ...)
standardGeneric("chol2inv")
<bytecode: 0x000000000eafd790>
<environment: 0x000000000eb06f10>
Methods may be defined for arguments: x
Use showMethods("chol2inv") for currently available ones.
Wyjście oferuje już wiele informacji. standardGeneric
jest wskaźnikiem funkcji S4. Metoda, aby zobaczyć zdefiniowane metody S4, jest oferowana pomocnie:
> showMethods(chol2inv)
Function: chol2inv (package base)
x="ANY"
x="CHMfactor"
x="denseMatrix"
x="diagonalMatrix"
x="dtrMatrix"
x="sparseMatrix"
getMethod
może być używane, aby zobaczyć kod źródłowy jednej z metod:
> getMethod("chol2inv", "diagonalMatrix")
Method Definition:
function (x, ...)
{
chk.s(...)
tcrossprod(solve(x))
}
<bytecode: 0x000000000ea2cc70>
<environment: namespace:Matrix>
Signatures:
x
target "diagonalMatrix"
defined "diagonalMatrix"
Istnieją również metody o bardziej złożonych podpisach dla każdej z metod, na przykład
require(raster)
showMethods(extract)
Function: extract (package raster)
x="Raster", y="data.frame"
x="Raster", y="Extent"
x="Raster", y="matrix"
x="Raster", y="SpatialLines"
x="Raster", y="SpatialPoints"
x="Raster", y="SpatialPolygons"
x="Raster", y="vector"
Aby zobaczyć kod źródłowy jednej z tych metod, należy podać cały podpis, np.
getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") )
Nie wystarczy podać częściowego podpisu
getMethod("extract",signature="SpatialPolygons")
#Error in getMethod("extract", signature = "SpatialPolygons") :
# No method found for function "extract" and signature SpatialPolygons
Funkcje, które wywołują funkcje niezerowe
W przypadku ts.union
, .cbindts
i .makeNamesTs
są funkcjami z stats
przestrzeń nazw. Kod źródłowy funkcji nieprzetworzonych można wyświetlić za pomocą operatora :::
lub getAnywhere
.
> stats:::.makeNamesTs
function (...)
{
l <- as.list(substitute(list(...)))[-1L]
nm <- names(l)
fixup <- if (is.null(nm))
seq_along(l)
else nm == ""
dep <- sapply(l[fixup], function(x) deparse(x)[1L])
if (is.null(nm))
return(dep)
if (any(fixup))
nm[fixup] <- dep
nm
}
<bytecode: 0x38140d0>
<environment: namespace:stats>
Funkcje wywołujące skompilowany kod
Zauważ, że "skompilowany" nie odnosi się do skompilowanego bajtowo kodu R utworzonego przez pakiet kompilatora. Linia <bytecode: 0x294e410>
na powyższym wyjściu wskazuje, że funkcja jest skompilowana bajtowo i nadal można wyświetlić źródło z wiersza poleceń R.
Funkcje wywołujące .C
, .Call
, .Fortran
, .External
, .Internal
, lub .Primitive
wywołują punkty wejścia w skompilowanym kodzie, więc będziesz musiał spojrzeć na źródła skompilowanego kodu, jeśli chcesz w pełni zrozumieć funkcję. to Lustro GitHub kodu źródłowego R jest przyzwoitym miejscem do rozpoczęcia. Funkcja pryr::show_c_source
może być użytecznym narzędziem, ponieważ przeniesie Cię bezpośrednio do strony GitHub dla wywołań .Internal
i .Primitive
. Opakowania mogą używać .C
, .Call
, .Fortran
, i .External
; ale nie .Internal
czy .Primitive
, ponieważ są one używane do wywoływania funkcji wbudowanych w R Tłumacz.
Wywołania niektórych z powyższych funkcji mogą używać obiektu zamiast ciągu znaków do odwoływania się do skompilowanej funkcji. W takich przypadkach obiekt należy do klasy "NativeSymbolInfo"
, "RegisteredNativeSymbol"
, lub "NativeSymbol"
; a wydrukowanie obiektu daje użyteczne informacje. Na przykład, optim
wywołuje .External2(C_optimhess, res$par, fn1, gr1, con)
(zauważ, że jest to C_optimhess
, a nie "C_optimhess"
). optim
Znajduje się w pakiecie stats, więc możesz wpisać stats:::C_optimhess
, aby zobaczyć informacje o wywołanej funkcji.
Skompilowany kod w pakiet
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 kompatybilnego z CRAN), z którego pakiet został pierwotnie zainstalowany. Funkcja download.packages()
może pobrać źródło pakietu dla Ciebie.
download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")
Spowoduje to pobranie wersji źródłowej pakietu Matrix i zapisanie odpowiedniego pliku .tar.gz
w bieżącym katalog. Kod źródłowy skompilowanych funkcji można znaleźć w katalogu src
nieskompresowanego i nie udostępnionego pliku. Krok rozpakowywania i rozpakowywania można wykonać poza R
, lub z wewnątrz {[54] } za pomocą funkcji untar()
. Możliwe jest połączenie kroku download I expansion w jedno wywołanie (należy pamiętać, że tylko jeden pakiet na raz może być pobrany i rozpakowany w ten sposób): {]}
untar(download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")[,2])
Alternatywnie, jeśli rozwój pakietu jest hostowany publicznie (np. poprzez GitHub, R-Forge , or RForge.net ), prawdopodobnie możesz przeglądać kod źródłowy online.
Skompilowany kod w pakiecie bazowym
Niektóre pakiety są uważane za pakiety "podstawowe". Pakiety te są dostarczane z R, a ich wersja jest zablokowana do wersji R. przykłady obejmują base
, compiler
, stats
, i utils
. W związku z tym nie są one dostępne jako oddzielne pakiety do pobrania na CRAN, jak opisano powyżej. Są raczej częścią drzewa źródłowego R w poszczególne katalogi pakietów pod /src/library/
. Jak uzyskać dostęp do źródła R opisano w następnej sekcji.
Skompilowany kod wbudowany w interpreter R
Jeśli chcesz zobaczyć 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 Winstona Changa na github mirror.
Uwe Ligges ' s r news article (PDF) (s. 43) is a good general odniesienie do sposobu wyświetlania kodu źródłowego funkcji .Internal
i .Primitive
. Podstawowe kroki to najpierw poszukać nazwy funkcji w src/main/names.c
, a następnie wyszukać nazwę "C-entry" w plikach w src/main/*
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26
Oprócz innych odpowiedzi na to pytanie i jego duplikatów, oto dobry sposób na uzyskanie kodu źródłowego funkcji pakietu bez konieczności wiedzieć, w którym pakiecie się znajduje.
np. jeśli chcemy mieć źródło dla randomForest::rfcv()
:
Do Wyświetl/edytuj w wyskakującym oknie:
edit(getAnywhere('rfcv'), file='source_rfcv.r')
Do przekierowanie do osobnego pliku :
capture.output(getAnywhere('rfcv'), file='source_rfcv.r')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-29 18:58:39
Zostanie ujawniona podczas debugowania za pomocą funkcji debug (). Załóżmy, że chcesz zobaczyć kod źródłowy w funkcji transpozycja t (). Samo wpisanie "t" nie ujawnia zbyt wiele.
>t
function (x)
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>
Ale, używając ' debug (functionName)', ujawnia kod bazowy, bez wewnętrznych.
> debug(t)
> t(co2)
debugging in: t(co2)
debug: UseMethod("t")
Browse[2]>
debugging in: t.ts(co2)
debug: {
cl <- oldClass(x)
other <- !(cl %in% c("ts", "mts"))
class(x) <- if (any(other))
cl[other]
attr(x, "tsp") <- NULL
t(x)
}
Browse[3]>
debug: cl <- oldClass(x)
Browse[3]>
debug: other <- !(cl %in% c("ts", "mts"))
Browse[3]>
debug: class(x) <- if (any(other)) cl[other]
Browse[3]>
debug: attr(x, "tsp") <- NULL
Browse[3]>
debug: t(x)
EDIT: debugonce() osiąga to samo bez konieczności używania undebug ()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-20 03:33:34
Nie widziałem jak to wpasowuje się w nurt głównej odpowiedzi, ale przez chwilę mnie to zaskoczyło, więc dodaję to tutaj:
Operatory Infiksowe
Aby zobaczyć kod źródłowy niektórych bazowych operatorów infiksowych (np., %%
, %*%
, %in%
), Użyj getAnywhere
, np.:
getAnywhere("%%")
# A single object matching ‘%%’ was found
# It was found in the following places
# package:base
# namespace:base
# with value
#
# function (e1, e2) .Primitive("%%")
Główna odpowiedź obejmuje, Jak następnie używać luster do kopania głębiej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-29 19:30:53
Dla funkcji nie-prymitywnych baza r zawiera funkcję o nazwie body()
, która zwraca ciało funkcji. Na przykład źródło funkcji print.Date()
można wyświetlić:
body(print.Date)
Wyprodukuje to:
{
if (is.null(max))
max <- getOption("max.print", 9999L)
if (max < length(x)) {
print(format(x[seq_len(max)]), max = max, ...)
cat(" [ reached getOption(\"max.print\") -- omitted",
length(x) - max, "entries ]\n")
}
else print(format(x), max = max, ...)
invisible(x)
}
Jeśli pracujesz w skrypcie i chcesz, aby kod funkcji był wektorem znaków, możesz go uzyskać.
capture.output(print(body(print.Date)))
Dostaniesz:
[1] "{"
[2] " if (is.null(max)) "
[3] " max <- getOption(\"max.print\", 9999L)"
[4] " if (max < length(x)) {"
[5] " print(format(x[seq_len(max)]), max = max, ...)"
[6] " cat(\" [ reached getOption(\\\"max.print\\\") -- omitted\", "
[7] " length(x) - max, \"entries ]\\n\")"
[8] " }"
[9] " else print(format(x), max = max, ...)"
[10] " invisible(x)"
[11] "}"
Po co miałbym to robić? Tworzyłem własny obiekt S3 (x
, gdzie class(x) = "foo"
) na podstawie listy. Jeden z listy członków (o nazwie "fun") była funkcja i chciałem print.foo()
, aby wyświetlić kod źródłowy funkcji, wcięty. Więc skończyłem z następującym fragmentem w print.foo()
:
sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0(" ", sourceVector, "\n"))
, który wcina i wyświetla kod powiązany z x[["fun"]]
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-09 23:34:04
Istnieje bardzo przydatna funkcja W R edit
new_optim <- edit(optim)
Otworzy kod źródłowy optim
używając edytora określonego W R options
, a następnie możesz go edytować i przypisać zmodyfikowaną funkcję do new_optim
. Bardzo podoba mi się Ta funkcja, aby wyświetlić kod lub debugować kod, np. wydrukować niektóre wiadomości lub zmienne, a nawet przypisać je do globalnych zmiennych do dalszego badania(oczywiście możesz użyć debug
).
Jeśli chcesz tylko wyświetlić kod źródłowy i nie chcesz denerwujących długi kod źródłowy wydrukowany na konsoli, możesz użyć
invisible(edit(optim))
Oczywiście nie można tego użyć do wyświetlenia kodu źródłowego C/C++ lub Fortran.
BTW, {[2] } może otwierać inne obiekty, takie jak lista, macierz itp., które następnie pokazują strukturę danych wraz z atrybutami. Funkcja de
może być użyta do otwarcia edytora Excela (jeśli obsługuje go GUI), aby zmodyfikować macierz lub ramkę danych i zwrócić nową. Jest to przydatne czasami, ale należy unikać w zwykłym przypadku, zwłaszcza, gdy macierz jest duży.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-04 23:39:33
Tak długo, jak funkcja jest napisana w czystym R, a nie w C / C++ / Fortran, można użyć następującego polecenia. W przeciwnym razie najlepszym sposobem jest debugowanie i użycie " jump do":
> functionBody(functionName)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-08 10:56:34
View([function_name])
- np. View(mean)
Upewnij się, że używasz wielkich liter [V]. Kod tylko do odczytu zostanie otwarty w edytorze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-11 02:45:22
Możesz również spróbować użyć print.function()
, która jest generyczna dla S3, aby uzyskać funkcję write w konsoli.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-26 11:45:54