Bessere Erklärung, wann Importe / Abhängigkeiten verwendet werden sollen


148

Das Handbuch " Schreiben von R-Erweiterungen " enthält die folgenden Anleitungen zur Verwendung von Importen oder Abhängigkeiten:

Die allgemeinen Regeln sind

  • Pakete, deren Namespace nur zum Laden des Pakets mithilfe der Bibliothek (pkgname) benötigt wird, müssen im Feld "Importe" und nicht im Feld "Abhängig" aufgeführt werden.
  • Pakete, die angehängt werden müssen, um das Paket mithilfe der Bibliothek (pkgname) erfolgreich zu laden, dürfen nur im Feld "Abhängig" aufgeführt werden.

Kann jemand etwas mehr Klarheit darüber schaffen? Woher weiß ich, wann für mein Paket nur Namespaces geladen werden müssen und wann ein Paket angehängt werden muss? Was sind Beispiele für beides? Ich denke, das typische Paket ist nur eine Sammlung von Funktionen, die manchmal Funktionen in anderen Paketen aufrufen (wo ein Teil der Arbeit bereits codiert wurde). Ist dieses Szenario 1 oder 2 oben?

Bearbeiten

Ich habe einen Blog-Beitrag mit einem Abschnitt zu diesem speziellen Thema geschrieben (Suche nach "Imports v Depends"). Die Grafiken erleichtern das Verständnis.


1
Ihr Blog-Beitrag hat mir alles über die Paketstruktur erzählt, als ich anfing, Module zu planen . Vielen Dank!
Konrad Rudolph

Antworten:


143

"Imports"ist sicherer als "Depends"(und macht ein Paket, das es verwendet, auch zu einem "besseren Bürger" im Vergleich zu anderen Paketen, die es verwenden "Depends").

Eine "Depends"Direktive versucht sicherzustellen, dass eine Funktion aus einem anderen Paket verfügbar ist, indem das andere Paket an den Hauptsuchpfad angehängt wird (dh die Liste der von zurückgegebenen Umgebungen search()). Diese Strategie kann jedoch vereitelt werden, wenn ein anderes Paket, das später geladen wird, eine identisch benannte Funktion früher in den Suchpfad einfügt. Chambers ( in Soda ) verwendet das Beispiel der Funktion "gam", die sowohl in der festgestellt wird , gamund mgcvPakete. Wenn zwei andere Pakete geladen würden, eines davon abhängig von gamund eines davon abhängig mgcv, würde die durch Aufrufe an gefundene Funktion von gam()der Reihenfolge abhängen, in der diese beiden Pakete angehängt wurden. Nicht gut.

Eine "Imports"Direktive sollte für jedes unterstützende Paket verwendet werden, dessen Funktionen in <imports:packageName>(unmittelbar danach gesucht <namespace:packageName>) platziert werden sollen, anstatt auf dem regulären Suchpfad. Wenn eines der Pakete im obigen Beispiel den "Imports"Mechanismus verwendet (der auch Anweisungen importoder importFromAnweisungen in der NAMESPACEDatei erfordert ), würde dies auf zwei Arten verbessert. (1) Das Paket würde selbst die Kontrolle darüber erlangen, welche mgcvFunktion verwendet wird. (2) Wenn der Hauptsuchpfad von den importierten Objekten ferngehalten wird, wird möglicherweise nicht einmal die Abhängigkeit des anderen Pakets von der anderen mgcvFunktion aufgehoben.

Aus diesem Grund ist die Verwendung von Namespaces eine so gute Vorgehensweise, warum sie jetzt von CRAN erzwungen wird und (insbesondere) warum die Verwendung "Imports"sicherer ist als die Verwendung "Depends".


Bearbeitet, um eine wichtige Einschränkung hinzuzufügen:

Es ist eine leider gemeinsame Ausnahme von der Beratung über: wenn Ihr Paket auf ein Paket basiert , Adie sich "Depends"auf ein anderes Paket B, das Paket wahrscheinlich benötigen anhängen Amit einer "DependsRichtlinie.

Dies liegt daran, dass die Funktionen im Paket Amit der Erwartung geschrieben wurden, dass das Paket Bund seine Funktionen an den search()Pfad angehängt werden .

Eine "Depends"Direktive lädt ein Paket und hängt es Aan. Zu diesem Zeitpunkt bewirkt die Aeigene "Depends"Direktive des Pakets in einer Kettenreaktion, dass das Paket ebenfalls Bgeladen und angehängt wird. Funktionen im Paket Akönnen dann die Funktionen im Paket finden, Bauf die sie sich verlassen.

Eine "Imports"Richtlinie wird geladen , aber nicht Paket anhängen Aund wird weder Last noch Paket anhängen B. ( "Imports"Immerhin erwartet , dass Paket Autoren des Namespace - Mechanismus verwenden, und dieses Paket Awird mit sein "Imports"auf alle Funktionen zu Punkt , Bdass sie den Zugang zu müssen.) Anrufe durch Ihre Funktionen auf alle Funktionen im Paket , Adie auf Funktionen im Paket verlassen BWillen folglich scheitern.

Die einzigen zwei Lösungen sind entweder:

  1. Lassen Sie Ihr Paket das Paket Amithilfe einer "Depends"Anweisung anhängen .
  2. Wenden Sie sich auf lange Sicht besser an den Paketbetreuer Aund bitten Sie ihn, den Namespace sorgfältiger zu erstellen (in den Worten von Martin Morgan in dieser Antwort ).

1
Nachdem wir kürzlich eine ähnliche Frage gestellt und kürzlich mächtig mit diesen Themen gerungen haben, handelt es sich um subtile und oft schlecht kommunizierte Konzepte. Ich verweise Sie hier für eine weitere Erklärung: stackoverflow.com/questions/7880355/…
Bryan Hanson

@BryanHanson - Danke, dass du die Notizen unter diesem Link geschrieben hast. Die Unterschiede zwischen Importsund DependsWRT Version Anforderungen und Prüfung von Beispielen in .RdDateien sind in der Tat subtil und es lohnt sich zu wissen.
Josh O'Brien

1
Die Einschränkung bezüglich Abhängigkeiten, die "Abhängigkeiten" verwenden, ist eine schreckliche Sache. Dies bedeutet, dass ich "Importe" in meinem Paket grundsätzlich nicht verwenden kann, bis alle anderen dies auch tun. = (
Ken Williams

Eine Sache, bei der ich immer noch unklar bin, ist, wenn ich ein Paket schreibe und möchte Imports: ggplot2, warum mein Paket dann die autoplotFunktion nicht findet . Offensichtlich Dependshängt die Paketbibliothek von ggplot2und so gibt es kein Problem. zB Ich habe eine Funktion, autoplot.myFunction() die das @import ggplot2Tag verwendet und mein Paket hat, Imports: ggplot2aber ich erhalte eine Fehlermeldung: Error in eval(expr, envir, enclos) : could not find function "autoplot"Wenn ich versuche, es zu verwenden.
Nathaneastwood

1
@ Willem Danke. Sie haben natürlich Recht, und ich habe die Antwort bearbeitet, um den irreführenden Inhalt zu beseitigen. Ein Teil dessen, was die Beantwortung dieser Angelegenheit kompliziert machte, ist, dass das OP, während es seine Frage mit Bezug auf die Dependsund ImportsAbschnitte von formulierte DESCRIPTION, wirklich fragte, was "Importieren" einer Funktion (anstatt "davon abhängig" zu sein) bedeutet. Da letzteres die Frage ist, die ich zu beantworten versucht habe (und - ich vermute - was die meisten Leute, die diese Antwort suchen, wissen wollen), werde ich die Antwort ansonsten unverändert lassen.
Josh O'Brien

31

Hadley Wickham gibt eine einfache Erklärung ( http://r-pkgs.had.co.nz/namespace.html ):

Durch Auflisten eines Pakets in Dependsoder wird Importssichergestellt, dass es bei Bedarf installiert wird. Der Hauptunterschied besteht darin, dass Importsdas Paket nur dort angehängt wird, wo Dependses geladen wird. Es gibt keine weiteren Unterschiede. [...]

Sofern es keinen guten Grund gibt, sollten Sie Pakete immer Importsnicht auflisten Depends. Dies liegt daran, dass ein gutes Paket in sich geschlossen ist und Änderungen an der globalen Umgebung (einschließlich des Suchpfads) minimiert. Die einzige Ausnahme ist, wenn Ihr Paket für die Verwendung in Verbindung mit einem anderen Paket ausgelegt ist. Zum Beispiel baut das analoge Paket auf vegan auf. Es ist nicht nützlich ohne vegan, also hat es vegan Dependsstatt Imports. Ebenso sollte ggplot2 wirklich von Skalen abhängen, anstatt sie zu importieren.


15

Chambers in SfDA sagt, dass "Importe" verwendet werden sollen, wenn dieses Paket einen "Namespace" -Mechanismus verwendet. Da alle Pakete jetzt über diese verfügen müssen, lautet die Antwort möglicherweise immer "Importe". In der Vergangenheit konnten Pakete ohne Namespaces geladen werden, und in diesem Fall müssten Sie Depends verwendet haben.


2
Wenn ein Paket in "Importe" angegeben ist und ich eine Funktion im Paket verwenden möchte, müssen meine eigenen Funktionen die Bibliothek aufrufen (...) oder sind alle Funktionen bereits im Suchpfad verfügbar? Was ist SfDA? Links?
SFun28

2
Software für die Datenanalyse : springer.com/statistics/computanional+statistics/book/… ... Was Ihre Fragen betrifft, weiß ich die Antwort nicht ohne weiteres, aber Sie könnten ein minimales Testpaket ziemlich einfach hacken und die Antwort finden empirisch ...
Ben Bolker

1
SfDA == "Software zur Datenanalyse". [65] unter r-project.org/doc/bib/R-books.html . Wenn ein Paket ein anderes Paket angibt, sollte eine Meldung angezeigt werden, die Sie über das Laden der abhängigen (encies) und importierten (ations) Informationen informiert, wenn Sie entweder library () oder require () an der Konsole verwenden. Ja, sie sollten dann verfügbar sein.
IRTFM

4
+1 - Dies ist auch mein starker Eindruck. Außerdem wird ein in Importen angegebenes Paket unmittelbar nach dem <namespace:packageName>, als Teil von durchsucht <imports:packageName>. Es library()ist kein weiterer Aufruf von erforderlich, und R benachrichtigt Sie beim Laden des ImportPakets nicht an der Konsole, es sei denn, das ed-Paket kann nicht gefunden werden.
Josh O'Brien

5

Hier ist eine einfache Frage, die Ihnen bei der Entscheidung hilft, welche Sie verwenden möchten:

Erfordert Ihr Paket, dass der Endbenutzer direkten Zugriff auf die Funktionen eines anderen Pakets hat?

  • NEIN -> Importe (häufigste Antwort)
  • JA -> Kommt darauf an

Sie sollten "Abhängig" nur verwenden, wenn Ihr Paket ein Add-On oder ein Begleiter zu einem anderen Paket ist, bei dem Ihr Endbenutzer Funktionen sowohl aus Ihrem Paket als auch aus dem Paket "Abhängig" in seinem Code verwendet. Wenn Ihr Endbenutzer nur mit Ihren Funktionen verbunden ist und das andere Paket nur hinter den Kulissen arbeitet, verwenden Sie stattdessen "Importe".

Die Einschränkung besteht darin, dass Ihr Code, wenn Sie 'Imports' wie gewohnt ein Paket hinzufügen, auf Funktionen aus diesem Paket verweisen muss, wobei die vollständige Namespace-Syntax verwendet wird, z. B. dplyr::mutate()statt nur mutate(). Es macht den Code etwas umständlicher zu lesen, aber es ist ein kleiner Preis für eine bessere Verpackungshygiene.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.