Warum gibt es in diesem Beispiel einen Unterschied zwischen Länge (f) und Länge (g)?

8
%Vor%     
Bai 23.12.2014, 17:08
quelle

1 Antwort

5

Zunächst ist length keine typische generische Funktion, sondern eine " Interne generische Funktion ". Sie können dies anhand der Definition sehen:

%Vor%

Vergleichen Sie dies mit einer typischen generischen Funktion:

%Vor%

length ruft direkt in .Primitive auf, das dann den Versand ausführen kann, wenn es den Aufruf selbst nicht verarbeitet; Der typische Ansatz ist der direkte Aufruf von UseMethod , der nur den Versand abwickelt. Beachten Sie auch, dass es keine Funktion length.default gibt, weil der Code im Aufruf .Primitive dies tut:

%Vor%

Ich bin mir nicht sicher, ob es vollständig definiert ist, wenn ein internes generisches System nach benutzerdefinierten Methoden sucht und wenn es nur interne Methoden verwendet; Ich denke, die allgemeine Idee ist, dass für eine Benutzer / Paket definierte (effektiv, Nicht-Kern-) Klasse die bereitgestellten Methoden verwendet werden. Aber das Überschreiben für interne Klassen kann oder kann nicht funktionieren.

Zusätzlich (obwohl dies für diesen Fall nicht unbedingt relevant ist) ist die Dokumentation selbst für eine typische generische Methode nicht eindeutig, was passieren sollte, wenn die Klasse implizit abgeleitet und nicht als Attribut angegeben wird. Erstens, was class() berichtet, ist eine Verschmelzung von Dingen. Auf der Hilfeseite class :

  

Viele R-Objekte haben ein class -Attribut, einen Zeichenvektor, der die Namen der Klassen angibt, von denen das Objekt erbt . Wenn das Objekt kein Klassenattribut hat, hat es eine implizite Klasse, "matrix" , "array" oder das Ergebnis von mode(x) (außer dass Integervektoren die implizite Klasse "integer" haben).

Also, obwohl class dasselbe für f und g zurückgibt, sind sie nicht gleich.

%Vor%

Nun, hier wird es mehrdeutig. Der Methodenversand wird in (mindestens) 2 Orten besprochen: die Hilfeseite class und die Hilfeseite UseMethod . UseMethod sagt:

  

Wenn eine Funktion, die UseMethod("fun") aufruft, auf ein Objekt mit dem Klassenattribut c("first", "second") angewendet wird, sucht das System nach einer Funktion namens fun.first und wendet sie, falls sie gefunden wird, auf das Objekt an. Wenn keine solche Funktion gefunden wird, wird eine Funktion namens fun.second versucht. Wenn kein Klassenname eine geeignete Funktion erzeugt, wird die Funktion fun.default verwendet, falls sie existiert oder ein Fehler auftritt.

Während class sagt:

  

Wenn eine generische Funktion fun auf ein Objekt mit dem Klassenattribut c("first", "second") angewendet wird, sucht das System nach einer Funktion namens fun.first und wendet sie, falls sie gefunden wird, auf das Objekt an. Wenn keine solche Funktion gefunden wird, wird eine Funktion namens fun.second versucht. Wenn kein Klassenname eine geeignete Funktion erzeugt, wird die Funktion fun.default verwendet (wenn sie existiert). Wenn es kein Klassenattribut gibt, wird die implizite Klasse und dann die Standardmethode versucht.

Der wirkliche Unterschied ist im letzten Satz, dass die class Seite das UseMethod nicht hat. UseMethod sagt nicht, was passiert, wenn es kein Attribut class gibt; class sagt, dass die implizite Klasse zum Versenden verwendet wird. Ihr Code scheint darauf hinzuweisen, dass das, was in class dokumentiert ist, nicht korrekt ist, da length.function für g aufgerufen worden wäre.

Was wirklich beim Methodenversand passiert, wenn kein Klassenattribut vorhanden ist, wird wahrscheinlich eine Prüfung des Quellcodes erfordern, da die Dokumentation scheinbar nicht hilft.

    
Brian Diggs 24.12.2014 08:09
quelle

Tags und Links