Lepsze wyjaśnienie, kiedy używać opcji Import / Depends


148

Podręcznik „ Pisanie rozszerzeń języka R ” zawiera następujące wskazówki dotyczące używania opcji Import lub zależności:

Ogólne zasady to

  • Pakiety, których przestrzeń nazw jest potrzebna tylko do załadowania pakietu przy użyciu biblioteki (pkgname), muszą być wymienione w polu „Import”, a nie w polu „Depends”.
  • Pakiety, które muszą zostać dołączone, aby pomyślnie załadować pakiet przy użyciu biblioteki (nazwa pakietu), muszą być wymienione tylko w polu „Zależności”.

Czy ktoś może wyjaśnić to nieco lepiej? Skąd mam wiedzieć, kiedy mój pakiet wymaga załadowania tylko przestrzeni nazw, a kiedy muszę dołączyć pakiet? Jakie są przykłady obu? Myślę, że typowy pakiet to po prostu zbiór funkcji, które czasami wywołują funkcje w innych pakietach (gdzie część pracy została już zakodowana). Czy ten scenariusz 1 czy 2 jest powyżej?

Edytować

Napisałem post na blogu z sekcją poświęconą temu konkretnemu tematowi (wyszukaj frazę „Imports v Depends”). Wizualizacje znacznie ułatwiają zrozumienie.


1
Twój post na blogu powiedział mi wszystko o strukturze pakietów, kiedy zacząłem planować moduły . Dzięki!
Konrad Rudolph

Odpowiedzi:


143

"Imports"jest bezpieczniejszy niż "Depends"(a także sprawia, że ​​korzystający z niego pakiet jest „lepszym obywatelem” w stosunku do innych pakietów, które go używają "Depends").

A "Depends"dyrektywa próby w celu zapewnienia, że funkcja z innego pakietu jest dostępna dołączając drugą paczkę do głównej ścieżce wyszukiwania (czyli listę środowisk zwróconych przez search()). Ta strategia może jednak zostać udaremniona, jeśli inny pakiet załadowany później umieści identycznie nazwaną funkcję wcześniej na ścieżce wyszukiwania. Chambers ( w SoDA ) używa przykładu funkcji "gam", który znajduje się zarówno w pakiecie , jak gami mgcv. Gdyby załadowano dwa inne pakiety, jeden z nich zależny, gama drugi zależny od mgcv, funkcja znaleziona przez wywołania gam()zależałaby od kolejności, w jakiej te dwa pakiety zostały dołączone. Niedobrze.

"Imports"Dyrektywa powinna być stosowana dla każdego pakietu wspierającego, którego funkcje mają być umieszczone w <imports:packageName>(poszukiwanej natychmiast po <namespace:packageName>), zamiast na zwykłej ścieżce wyszukiwania. Gdyby któryś z pakietów w powyższym przykładzie używał "Imports"mechanizmu (który również wymaga importlub importFromdyrektyw w NAMESPACEpliku), sytuacja uległaby poprawie na dwa sposoby. (1) Pakiet sam zyskałby kontrolę nad mgcvużywaną funkcją. (2) Utrzymując główną ścieżkę wyszukiwania z dala od importowanych obiektów, nie spowodowałoby to nawet potencjalnego zerwania zależności innego pakietu od innej mgcvfunkcji.

Dlatego używanie przestrzeni nazw jest tak dobrą praktyką, dlatego jest obecnie wymuszane przez CRAN i (w szczególności), dlaczego używanie "Imports"jest bezpieczniejsze niż używanie "Depends".


Zmieniono, aby dodać ważne zastrzeżenie:

Jest jeden niestety powszechne wyjątkiem rad powyżej: jeśli pakiet opiera się na pakiet A, który sam "Depends"na inny pakiet B, pakiet będzie prawdopodobnie musiał dołączyć Az "Dependsdyrektywą.

Dzieje się tak, ponieważ funkcje w pakiecie Azostały napisane z oczekiwaniem, że pakiet Bi jego funkcje zostaną dołączone do search()ścieżki .

"Depends"Dyrektywy ładuje i dołączać pakiet A, w którym to momencie pakiet Ajest własny "Depends"Dyrektywa będzie w reakcji łańcuchowej pakiet przyczyną Bbyć ładowane i dołączony również. Funkcje w pakiecie Abędą wtedy mogły znaleźć funkcje w pakiecie, Bna których polegają.

"Imports"Dyrektywa będzie ładować, ale nie przywiązują pakiet Ai będzie ani obciążenia ani dołączyć pakiet B. ( "Imports"Mimo wszystko oczekuje, że autorzy pakietów korzysta mechanizm przestrzeni nazw, a pakiet Abędzie używał "Imports"do punktu do jakichkolwiek funkcji w Bktóre potrzebują to dostęp.) Połączeń telefonicznych funkcji do jakichkolwiek funkcji w pakiecie A, które opierają się na funkcjach w opakowaniu Bwoli w konsekwencji zawiedzie.

Jedyne dwa rozwiązania to:

  1. Niech twój pakiet dołączy pakiet Aza pomocą "Depends"dyrektywy.
  2. Lepiej na dłuższą metę, skontaktuj się z opiekunem pakietu Ai poproś go, aby wykonał bardziej ostrożną pracę przy konstruowaniu ich przestrzeni nazw (słowami Martina Morgana w tej powiązanej odpowiedzi ).

1
Ponieważ ostatnio zadawałem podobne pytanie i ostatnio mocno zmagałem się z tymi problemami, są to subtelne i często źle komunikowane koncepcje. Skieruję cię tutaj po inne wyjaśnienie: stackoverflow.com/questions/7880355/ ...
Bryan Hanson,

@BryanHanson - Dziękuję za napisanie uwag pod tym linkiem. Różnice między wymaganiami wersji Importsi Dependswrt oraz sprawdzaniem przykładów w .Rdplikach są rzeczywiście subtelne i warte poznania.
Josh O'Brien,

1
Zastrzeżenie dotyczące zależności, które używają „Zależności”, jest okropną rzeczą. Oznacza to, że w zasadzie nie mogę używać opcji „Import” w moim pakiecie, dopóki wszyscy inni też tego nie zrobią. = (
Ken Williams,

Nadal nie jestem pewien, czy piszę pakiet i chcę Imports: ggplot2, dlaczego mój pakiet nie znajduje autoplotfunkcji? Oczywiście Dependsdołącza bibliotekę pakietów, ggplot2więc nie ma problemu. np. mam funkcję, autoplot.myFunction() która używa @import ggplot2tagu, a mój pakiet ma, Imports: ggplot2ale pojawia się błąd: Error in eval(expr, envir, enclos) : could not find function "autoplot"kiedy próbuję go użyć.
nathaneastwood

1
@ Willem Thanks. Masz oczywiście rację i zredagowałem odpowiedź, aby wyjaśnić mylącą treść. Częścią tego, co utrudniało udzielenie odpowiedzi, było to, że podczas gdy OP sformułował swoje pytanie w odniesieniu do sekcji Dependsi , tak naprawdę pytał o to, co oznacza „importowanie” funkcji (a nie „zależność” od niej). Ponieważ to ostatnie jest pytaniem, na które próbowałem odpowiedzieć (i - jak podejrzewam - co większość osób szukających tej odpowiedzi chce wiedzieć), w przeciwnym razie pozostawię odpowiedź bez zmian. ImportsDESCRIPTION
Josh O'Brien

31

Hadley Wickham podaje proste wyjaśnienie ( http://r-pkgs.had.co.nz/namespace.html ):

Wystawianie pakietu na liście Dependslub Importszapewnia, że ​​zostanie on zainstalowany w razie potrzeby. Główna różnica polega na tym, że tam, gdzie Importspo prostu ładuje paczkę, Dependsdołącza ją. Nie ma innych różnic. […]

O ile nie ma dobrego powodu, zawsze powinieneś wyświetlać pakiety w Importsnie Depends. Dzieje się tak, ponieważ dobry pakiet jest samowystarczalny i minimalizuje zmiany w środowisku globalnym (w tym w ścieżce wyszukiwania). Jedynym wyjątkiem jest sytuacja, gdy Twój pakiet jest przeznaczony do użytku w połączeniu z innym pakietem. Na przykład pakiet analogowy opiera się na wegańskim. Nie jest to przydatne bez wegan, więc Dependszamiast wegan jest Imports. Podobnie, ggplot2 powinien naprawdę zależeć od skal, a nie importować go.


15

Chambers w SfDA mówi, że należy używać opcji „Import”, gdy ten pakiet używa mechanizmu „przestrzeni nazw”, a ponieważ wszystkie pakiety muszą teraz je mieć, odpowiedzią może być teraz zawsze „Import”. W przeszłości pakiety mogły być ładowane bez rzeczywistych przestrzeni nazw iw takim przypadku musiałbyś użyć Depends.


2
kiedy pakiet jest określony w "importach" i chcę użyć funkcji w pakiecie, czy moje własne funkcje muszą wywoływać bibliotekę (...), czy też wszystkie funkcje są już dostępne w ścieżce wyszukiwania? Co to jest SfDA? spinki do mankietów?
SFun28,

2
Oprogramowanie do analizy danych : springer.com/statistics/computanional+statistics/book/ ... ... jeśli chodzi o twoje pytania, nie znam odpowiedzi od ręki, ale możesz łatwo zhakować minimalny pakiet testowy i znaleźć odpowiedź empirycznie ...
Ben Bolker

1
SfDA == "Oprogramowanie do analizy danych". [65] na r-project.org/doc/bib/R-books.html . Jeśli pakiet określa inny pakiet, powinieneś zobaczyć komunikat informujący o ładowaniu zależności (enities) i imporcie (ations), gdy używasz biblioteki () lub require () na konsoli. Tak, wtedy powinny być dostępne.
IRTFM

4
+1 - To też jest moje mocne wrażenie. Ponadto pakiet określony w importach będzie przeszukiwany bezpośrednio po <namespace:packageName>, jako część <imports:packageName>. Żadne dalsze wywołanie nie library()jest potrzebne, a R nie powiadomi cię przy konsoli w czasie ładowania pakietu, chyba że Importnie można znaleźć pakietu ed.
Josh O'Brien,

5

Oto proste pytanie, które pomoże Ci zdecydować, którego użyć:

Czy Twój pakiet wymaga, aby użytkownik końcowy miał bezpośredni dostęp do funkcji innego pakietu?

  • NIE -> Import (najczęstsza odpowiedź)
  • TAK -> Zależy

Jedynym przypadkiem, w którym powinieneś używać opcji „Depends”, jest sytuacja, gdy Twój pakiet jest dodatkiem lub dodatkiem do innego pakietu, w którym użytkownik końcowy będzie używał funkcji zarówno z Twojego pakietu, jak i pakietu „Depends” w swoim kodzie. Jeśli twój użytkownik końcowy będzie łączył się tylko z twoimi funkcjami, a drugi pakiet będzie wykonywał pracę tylko za kulisami, użyj zamiast tego opcji „Import”.

Jedynym zastrzeżeniem jest to, że jeśli dodasz pakiet do 'Importów', jak zwykle powinieneś, twój kod będzie musiał odnosić się do funkcji z tego pakietu, używając pełnej składni przestrzeni nazw, np. dplyr::mutate()Zamiast just mutate(). Sprawia to, że kod jest nieco trudniejszy do odczytania, ale jest to niewielka cena za lepszą higienę opakowania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.