Ich möchte im Quellcode nach einer Funktion suchen, um zu sehen, wie sie funktioniert. Ich weiß, dass ich eine Funktion drucken kann, indem ich ihren Namen an der Eingabeaufforderung eingebe:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
Was bedeutet in diesem Fall UseMethod("t")
? Wie finde ich den Quellcode, der tatsächlich verwendet wird, zum Beispiel : t(1:10)
?
Gibt es einen Unterschied zwischen wann ich sehe UseMethod
und wann ich sehe standardGeneric
und showMethods
wie bei 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.
In anderen Fällen kann ich sehen, dass R-Funktionen aufgerufen werden, aber ich kann den Quellcode für diese Funktionen nicht finden.
> 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
Wie finde ich Funktionen wie .cbindts
und .makeNamesTs
?
In noch anderen Fällen gibt es ein bisschen R-Code, aber die meiste Arbeit scheint woanders erledigt zu sein.
> 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")
Wie finde ich heraus, was die .Primitive
Funktion tut? In ähnlicher Weise einige Funktionen aufrufen .C
, .Call
, .Fortran
, .External
, oder .Internal
. Wie finde ich den Quellcode für diese?
Antworten:
UseMethod("t")
sagt Ihnen, dasst()
es sich um eine ( S3 ) generische Funktion handelt, die Methoden für verschiedene Objektklassen enthält.Das Versandverfahren nach der S3-Methode
Für S3-Klassen können Sie die
methods
Funktion verwenden, um die Methoden für eine bestimmte generische Funktion oder Klasse aufzulisten."Nicht sichtbare Funktionen sind mit einem Sternchen versehen" bedeutet, dass die Funktion nicht aus dem Namespace ihres Pakets exportiert wird. Sie können den Quellcode weiterhin über die
:::
Funktion (dhstats:::t.ts
) oder mithilfe von anzeigengetAnywhere()
.getAnywhere()
ist nützlich, weil Sie nicht wissen müssen, von welchem Paket die Funktion stammt.Das S4-Methodenversandsystem
Das S4-System ist ein neueres Methodenversandsystem und eine Alternative zum S3-System. Hier ist ein Beispiel für eine S4-Funktion:
Die Ausgabe bietet bereits viele Informationen.
standardGeneric
ist ein Indikator für eine S4-Funktion. Die Methode zum Anzeigen definierter S4-Methoden wird hilfreich angeboten:getMethod
kann verwendet werden, um den Quellcode einer der folgenden Methoden anzuzeigen:Es gibt beispielsweise auch Methoden mit komplexeren Signaturen für jede Methode
Um den Quellcode für eine dieser Methoden anzuzeigen, muss die gesamte Signatur bereitgestellt werden, z
Es reicht nicht aus, die Teilunterschrift zu liefern
Funktionen, die nicht exportierte Funktionen aufrufen
Im Fall von
ts.union
,.cbindts
und.makeNamesTs
sind unexported Funktionen aus demstats
Namespace. Sie können den Quellcode nicht exportierter Funktionen mit dem:::
Operator oder anzeigengetAnywhere
.Funktionen, die kompilierten Code aufrufen
Beachten Sie, dass "kompiliert" nicht auf bytekompilierten R-Code verweist, wie er vom Compilerpaket erstellt wurde. Die
<bytecode: 0x294e410>
Zeile in der obigen Ausgabe zeigt an, dass die Funktion bytekompiliert ist und Sie die Quelle weiterhin über die R-Befehlszeile anzeigen können.Funktionen dieser Anruf
.C
,.Call
,.Fortran
,.External
,.Internal
, oder.Primitive
Einstiegspunkte in kompilierten Code aufrufen, so dass Sie auf Quellen des kompilierten Codes suchen müssen, wenn Sie die Funktion vollständig verstehen wollen. Dieser GitHub-Spiegel des R-Quellcodes ist ein guter Ausgangspunkt. Die Funktionpryr::show_c_source
kann ein nützliches Werkzeug sein, da sie Sie direkt zu einer GitHub-Seite für.Internal
und.Primitive
Aufrufen führt. Pakete können verwendet werden.C
,.Call
,.Fortran
und.External
; aber nicht.Internal
oder.Primitive
, weil diese verwendet werden, um Funktionen aufzurufen, die in den R-Interpreter eingebaut sind.Aufrufe einiger der oben genannten Funktionen können ein Objekt anstelle einer Zeichenfolge verwenden, um auf die kompilierte Funktion zu verweisen. In diesen Fällen ist das Objekt der Klasse
"NativeSymbolInfo"
,"RegisteredNativeSymbol"
oder"NativeSymbol"
; und das Drucken des Objekts liefert nützliche Informationen. Zum Beispieloptim
Anrufe.External2(C_optimhess, res$par, fn1, gr1, con)
(beachten Sie, dass dies nicht derC_optimhess
Fall ist"C_optimhess"
).optim
befindet sich im Statistikpaket, sodass Sie eingeben könnenstats:::C_optimhess
, um Informationen zur aufgerufenen kompilierten Funktion anzuzeigen.Kompilierter Code in einem Paket
Wenn Sie kompilierten Code in einem Paket anzeigen möchten, müssen Sie die Paketquelle herunterladen / entpacken. Die installierten Binärdateien reichen nicht aus. Der Quellcode eines Pakets ist im selben CRAN-Repository (oder CRAN-kompatiblen Repository) verfügbar, aus dem das Paket ursprünglich installiert wurde. Die
download.packages()
Funktion kann die Paketquelle für Sie abrufen.Dadurch wird die Quellversion des Matrix-Pakets heruntergeladen und die entsprechende
.tar.gz
Datei im aktuellen Verzeichnis gespeichert. Der Quellcode für kompilierte Funktionen befindet sich imsrc
Verzeichnis der unkomprimierten und nicht tarierten Datei. Der Dekomprimierungs- und Entpackungsschritt kann außerhalbR
oder von innenR
mithilfe deruntar()
Funktion ausgeführt werden. Es ist möglich, den Download- und Erweiterungsschritt in einem einzigen Aufruf zu kombinieren (beachten Sie, dass auf diese Weise jeweils nur ein Paket heruntergeladen und entpackt werden kann):Wenn die Paketentwicklung öffentlich gehostet wird (z. B. über GitHub , R-Forge oder RForge.net ), können Sie den Quellcode wahrscheinlich auch online durchsuchen.
Kompilierter Code in einem Basispaket
Bestimmte Pakete gelten als "Basis" -Pakete. Diese Pakete versenden mit R und deren Version auf die Version von R. Beispiele gesperrt sind
base
,compiler
,stats
, undutils
. Daher sind sie nicht wie oben beschrieben als separate herunterladbare Pakete auf CRAN verfügbar. Sie sind vielmehr Teil des R-Quellbaums in einzelnen Paketverzeichnissen unter/src/library/
. Der Zugriff auf die R-Quelle wird im nächsten Abschnitt beschrieben.In den R-Interpreter integrierter kompilierter Code
Wenn Sie den im R-Interpreter integrierten Code anzeigen möchten, müssen Sie die R-Quellen herunterladen / entpacken. Oder Sie können die Quellen online über das R Subversion-Repository oder den Github-Spiegel von Winston Chang anzeigen .
Der R-Nachrichtenartikel (PDF) von Uwe Ligges (S. 43) ist eine gute allgemeine Referenz zum Anzeigen des Quellcodes
.Internal
und der.Primitive
Funktionen. Die grundlegenden Schritte bestehen darin, zuerst nach dem Funktionsnamen in zusrc/main/names.c
suchen und dann in den Dateien in nach dem Namen "C-Eintrag" zu suchensrc/main/*
.quelle
RStudio
, wird versucht, die Quelle für die Funktion zu ziehen, bei der sich Ihr Textcursor befindet, wenn Sie dieF2
Taste drücken.scale
das ist S3 - ich habe es bekommenUseMethod("scale")
und dann benutztgetAnywhere(scale.default)
). Aber einfache Funktionen funktionieren einwandfrei.Zusätzlich zu den anderen Antworten auf diese Frage und ihre Duplikate ist hier eine gute Möglichkeit, den Quellcode für eine Paketfunktion abzurufen, ohne wissen zu müssen, in welchem Paket sie sich befindet. Beispiel: Wenn wir die Quelle für Folgendes benötigen
randomForest::rfcv()
:So zeigen Sie es in einem Popup-Fenster an / bearbeiten es:
So leiten Sie in eine separate Datei um :
quelle
View(foo)
; Wofoo
war eine Funktion aus einem bereits geladenen Paket.edit()
einen Texteditor (nach Wahl des Benutzers) , währendView()
ein Tabellenkalkulations-Viewer vom Typ Excel für Daten geöffnet wird. Letzterer eignet sich zum Durchsuchen von (mehrspaltigen) Daten, ist jedoch normalerweise für Code mit einer anderen Länge als Spielzeug schrecklich. Wie ich zum Beispiel anspreche, ist das erste, was ich beim Durchsuchen einer Funktion tun möchte, das Überspringen / Reduzieren / Dummy aller Arg-Parsing- und Standard-Aktionslogik, um zu sehen, was die Funktion tatsächlich tut .Es wird angezeigt, wenn Sie mit der Funktion debug () debuggen. Angenommen, Sie möchten den zugrunde liegenden Code in der Transponierungsfunktion t () sehen. Nur 't' zu tippen, verrät nicht viel.
Bei Verwendung von 'debug (functionName)' wird jedoch der zugrunde liegende Code ohne Interna angezeigt.
BEARBEITEN : debugonce () erreicht dasselbe, ohne undebug () verwenden zu müssen
quelle
debugonce
anstelle vondebug
in diesem Fall zu verwenden.Für nicht-primitive Funktionen enthält R base eine Funktion namens
body()
, die den Funktionskörper zurückgibt. Zum Beispiel kann die Quelle derprint.Date()
Funktion angezeigt werden:wird dies produzieren:
Wenn Sie in einem Skript arbeiten und den Funktionscode als Zeichenvektor verwenden möchten, können Sie ihn abrufen.
Kriege dich:
Warum sollte ich so etwas tun wollen? Ich habe ein benutzerdefiniertes S3-Objekt (
x
, woclass(x) = "foo"
) basierend auf einer Liste erstellt. Eines der Listenmitglieder (mit dem Namen "fun") war eine Funktion, und ich wollteprint.foo()
den eingerückten Funktionsquellcode anzeigen. So kam ich zu folgendem Ausschnittprint.foo()
:Hiermit wird der zugeordnete Code eingerückt und angezeigt
x[["fun"]]
.quelle
Ich habe nicht gesehen, wie dies in den Fluss der Hauptantwort passt, aber es hat mich eine Weile verblüfft, also füge ich es hier hinzu:
Infix-Operatoren
Um zu sehen, den Quellcode einiger Basis Infixoperatoren (zB
%%
,%*%
,%in%
), verwendengetAnywhere
, zum Beispiel:Die Hauptantwort beschreibt, wie man dann Spiegel verwendet, um tiefer zu graben.
quelle
getAnywhere
. Oder Sie können einfach Backticks verwenden, wenn Sie den Namen des Operators bereits kennen :`%in%`
.getAnywhere
wird auch in Ihrer Antwort erwähnt, aber ich denke, ein spezifischer Verweis auf Infix ist nützlich für zukünftige Verweise auf diese Antwort - ich habe diese Seite oft gelesen und war immer noch etwas ratlos, als ich versuchte, Code für solche Funktionen für a zu finden während - und ich dachte nicht, dass es in den Fluss einer der anderen Antworten passt (die beidegetAnywhere
für einen anderen Zweck verwenden).Es gibt eine sehr praktische Funktion in R.
edit
Es öffnet den Quellcode der
optim
Verwendung des in Rs angegebenen Editorsoptions
, und dann können Sie ihn bearbeiten und die geänderte Funktion zuweisennew_optim
. Ich mag diese Funktion sehr, um Code anzuzeigen oder den Code zu debuggen, z. B. einige Nachrichten oder Variablen zu drucken oder sie sogar globalen Variablen zur weiteren Untersuchung zuzuweisen (natürlich können Sie sie verwendendebug
).Wenn Sie nur den Quellcode anzeigen möchten und nicht möchten, dass der nervige lange Quellcode auf Ihrer Konsole gedruckt wird, können Sie ihn verwenden
Dies kann natürlich nicht zum Anzeigen von C / C ++ - oder Fortran-Quellcode verwendet werden.
Übrigens,
edit
kann andere Objekte wie Liste, Matrix usw. öffnen, die dann auch die Datenstruktur mit Attributen anzeigen. Mit dieser Funktionde
können Sie einen Excel-ähnlichen Editor öffnen (sofern die GUI dies unterstützt), um die Matrix oder den Datenrahmen zu ändern und den neuen zurückzugeben. Dies ist manchmal praktisch, sollte aber im Normalfall vermieden werden, insbesondere wenn Ihre Matrix groß ist.quelle
Solange die Funktion in reinem R und nicht in C / C ++ / Fortran geschrieben ist, kann man Folgendes verwenden. Ansonsten ist der beste Weg das Debuggen und Verwenden von " Sprung in ":
quelle
body
.identical(functionBody, body)
istTRUE
.base::body
undmethods::functionBody
obwohl sie nicht in der Lage sind, enttäuscht zu werden.body
könnte auch überschrieben werden: rdocumentation.org/search?q=bodyIn RStudio gibt es (mindestens) drei Möglichkeiten:
View
(Funktionsname) (wie oben angegeben)Ein neuer Bereich mit dem Quellcode wird geöffnet. Wenn Sie .Primitive oder .C erreichen, benötigen Sie leider eine andere Methode.
quelle
View([function_name])
- z.B.View(mean)
Stellen Sie sicher, dass Sie Großbuchstaben [V] verwenden. Der schreibgeschützte Code wird im Editor geöffnet.quelle
Sie können auch versuchen
print.function()
, S3 generisch zu verwenden, um die Funktion in die Konsole zu schreiben.quelle
print.function()
ist eine S3- Methode . Das Generikum istprint()
. Und es ist im Allgemeinen keine gute Idee, Methoden direkt aufzurufen. Das macht den gesamten Zweck der generischen Funktionen und des Methodenversands zunichte.