Migliore spiegazione di quando utilizzare le importazioni / dipendenze


148

Il manuale " Scrivere estensioni R " fornisce le seguenti indicazioni su quando utilizzare le importazioni o dipende:

Le regole generali sono

  • I pacchetti il ​​cui spazio dei nomi è necessario solo per caricare il pacchetto utilizzando la libreria (pkgname) devono essere elencati nel campo "Importazioni" e non nel campo "Dipende".
  • I pacchetti che devono essere collegati per caricare correttamente il pacchetto utilizzando la libreria (pkgname) devono essere elencati solo nel campo "Dipende".

Qualcuno può fornire un po 'più di chiarezza su questo? Come faccio a sapere se il mio pacchetto necessita solo di spazi dei nomi caricati rispetto a quando ho bisogno di un pacchetto da allegare? Quali sono esempi di entrambi? Penso che il pacchetto tipico sia solo una raccolta di funzioni che a volte chiamano funzioni in altri pacchetti (in cui un po 'di lavoro è già stato codificato). Questo scenario 1 o 2 è sopra?

modificare

Ho scritto un post sul blog con una sezione su questo argomento specifico (cercare "Imports v Depends"). La grafica rende molto più facile da capire.


1
Il tuo post sul blog mi ha raccontato tutto sulla struttura del pacchetto, quando ho iniziato a pianificare i moduli . Grazie!
Konrad Rudolph,

Risposte:


143

"Imports"è più sicuro di "Depends"(e rende anche un pacchetto usandolo un "cittadino migliore" rispetto ad altri pacchetti che usano "Depends").

Una "Depends"direttiva tenta di garantire la disponibilità di una funzione di un altro pacchetto collegando l'altro pacchetto al percorso di ricerca principale (ovvero l'elenco degli ambienti restituiti da search()). Questa strategia può tuttavia essere contrastata se un altro pacchetto, caricato in un secondo momento, inserisce una funzione con nome identico in precedenza sul percorso di ricerca. Chambers ( in SoDA ) usa l'esempio della funzione "gam", che si trova in entrambi i pacchetti game mgcv. Se fossero stati caricati altri due pacchetti, uno a seconda game uno a seconda mgcv, la funzione trovata dalle chiamate gam()dipenderebbe dall'ordine in cui erano collegati quei due pacchetti. Non bene.

Una "Imports"direttiva dovrebbe essere utilizzata per qualsiasi pacchetto di supporto le cui funzioni devono essere inserite <imports:packageName>(ricercate immediatamente dopo <namespace:packageName>), anziché sul normale percorso di ricerca. Se uno dei pacchetti nell'esempio sopra usasse il "Imports"meccanismo (che richiede anche importo importFromdirettive nel NAMESPACEfile), le cose sarebbero migliorate in due modi. (1) Il pacchetto otterrebbe esso stesso il controllo su quale mgcvfunzione viene utilizzata. (2) Mantenendo il percorso di ricerca principale libero dagli oggetti importati, non si spezzerebbe nemmeno potenzialmente la dipendenza dell'altro pacchetto dall'altra mgcvfunzione.

Questo è il motivo per cui l'utilizzo degli spazi dei nomi è una buona pratica, perché ora è applicato da CRAN e (in particolare) perché l'uso "Imports"è più sicuro dell'uso "Depends".


Modificato per aggiungere un avvertimento importante:

V'è un'eccezione, purtroppo, comune alla consigli di cui sopra: se il pacchetto si basa su un pacchetto che si da un altro pacchetto , il pacchetto sarà probabilmente necessario collegare con una direttiva.A"Depends"BA"Depends

Questo perché le funzioni nel pacchetto Asono state scritte con l'aspettativa che il pacchetto Be le sue funzioni siano associate al search()percorso .

Una "Depends"direttiva caricherà e allegherà il pacchetto A, a quel punto Ala "Depends"direttiva del pacchetto stesso , in una reazione a catena, causerà Banche il caricamento e il collegamento del pacchetto . Le funzioni nel pacchetto Asaranno quindi in grado di trovare le funzioni nel pacchetto Bsu cui si basano.

Una "Imports"direttiva caricherà ma non allegherà il pacchetto Ae non caricherà alleggerà il pacchetto B. ( "Imports", Dopo tutto, si aspetta che gli scrittori del pacchetto utilizzano il meccanismo di namespace, e quel pacchetto Asaranno utilizzare "Imports"per puntare a qualsiasi funzioni Bche hanno bisogno di accedere a.) Chiama per le funzioni di tutte le funzioni in pacchetto Ache si basano sulle funzioni nella confezione Bvolontà di conseguenza fallire.

Le uniche due soluzioni sono:

  1. Chiedi al tuo pacchetto di allegare il pacchetto Ausando una "Depends"direttiva.
  2. Meglio a lungo termine, contattare il manutentore del pacchetto Ae chiedere loro di fare un lavoro più attento nel costruire il proprio spazio dei nomi (nelle parole di Martin Morgan in questa risposta correlata ).

1
Avendo di recente posto una domanda simile e recentemente lottato potentemente con questi problemi, questi sono concetti sottili e spesso mal comunicati. Ti farò riferimento qui per un'altra spiegazione: stackoverflow.com/questions/7880355/…
Bryan Hanson,

@BryanHanson - Grazie per aver scritto le note su quel link. Le differenze tra i requisiti di versione Importse Dependswrt e il controllo degli esempi nei .Rdfile sono davvero sottili e vale la pena conoscerle.
Josh O'Brien,

1
L'avvertenza sulle dipendenze che usano 'Dipende' è una cosa orribile. Significa che praticamente non posso usare "Import" nel mio pacchetto fino a quando non lo sono anche tutti gli altri. = (
Ken Williams,

Una cosa su cui non sono ancora chiaro è, se sto scrivendo un pacchetto, e voglio farlo Imports: ggplot2, perché il mio pacchetto non trova la autoplotfunzione? Ovviamente Dependsallega la libreria di pacchetti di ggplot2e quindi non ci sono problemi. ad es. ho una funzione autoplot.myFunction() che usa il @import ggplot2tag e il mio pacchetto ha Imports: ggplot2ma ricevo un errore: Error in eval(expr, envir, enclos) : could not find function "autoplot"quando provo ad usarlo.
nathaneastwood,

1
@Willem Grazie. Naturalmente hai ragione e ho modificato la risposta per chiarire il contenuto fuorviante. Parte di ciò che ha reso complicata la risposta è che, mentre l'OP ha inquadrato la sua domanda con riferimento alle sezioni Dependse Importsdi DESCRIPTION, stava davvero chiedendo cosa significhi "importare" una funzione (piuttosto che "dipendere" da essa). Poiché quest'ultima è la domanda a cui ho tentato di rispondere (e - sospetto - ciò che la maggior parte delle persone che cercano questa risposta vogliono sapere), lascerò la risposta altrimenti invariata.
Josh O'Brien,

31

Hadley Wickham fornisce una semplice spiegazione ( http://r-pkgs.had.co.nz/namespace.html ):

Elencare un pacchetto in uno Dependso entrambi Importsgarantisce che sia installato quando necessario. La differenza principale è che dove Importssolo carica il pacchetto, lo Dependsallega. Non ci sono altre differenze. [...]

A meno che non ci sia una buona ragione altrimenti, dovresti sempre elencare i pacchetti in Importsno Depends. Questo perché un buon pacchetto è autonomo e minimizza le modifiche all'ambiente globale (incluso il percorso di ricerca). L'unica eccezione è se il pacchetto è progettato per essere utilizzato insieme a un altro pacchetto. Ad esempio, il pacchetto analogico si basa su vegan. Non è utile senza vegan, quindi ha vegan Dependsinvece di Imports. Allo stesso modo, ggplot2 dovrebbe davvero dipendere dalle scale, piuttosto che importarlo.


15

Chambers in SfDA dice di usare 'Import' quando questo pacchetto usa un meccanismo 'namespace' e dato che ora tutti i pacchetti devono averli, allora la risposta potrebbe essere sempre usare 'Import'. In passato i pacchetti avrebbero potuto essere caricati senza effettivamente avere spazi dei nomi e in quel caso avresti dovuto usare Depends.


2
quando un pacchetto è specificato in "importazioni" e voglio usare una funzione nel pacchetto, le mie funzioni devono chiamare la libreria (...) o tutte le funzioni sono già disponibili nel percorso di ricerca? Inoltre, cos'è SfDA? link?
SFun28,

2
Software per l'analisi dei dati : springer.com/statistics/computanional+statistics/book/… ... per quanto riguarda le tue domande, non conosco la risposta in maniera diretta, ma potresti hackerare abbastanza facilmente un pacchetto di test minimo e trovare la risposta empiricamente ...
Ben Bolker, il

1
SfDA == "Software per analisi dei dati". [65] su r-project.org/doc/bib/R-books.html . Se un pacchetto specifica un altro pacchetto, dovresti visualizzare un messaggio che ti informa sul caricamento di depend (encies) e import (ations) quando usi la libreria () o request () sulla console. Sì, dovrebbero essere disponibili.
IRTFM,

4
+1 - Anche questa è la mia impressione forte. Inoltre, un pacchetto specificato nelle importazioni verrà cercato immediatamente dopo <namespace:packageName>, come parte di <imports:packageName>. Non library()è necessaria alcuna ulteriore chiamata a , e R non ti notificherà alla console al momento del caricamento del pacchetto a meno Importche non sia possibile trovare il pacchetto ed.
Josh O'Brien,

5

Ecco una semplice domanda per aiutarti a decidere quale utilizzare:

Il tuo pacchetto richiede all'utente finale di avere accesso diretto alle funzioni di un altro pacchetto?

  • NO -> Importazioni (risposta più comune)
  • SÌ -> Dipende

L'unica volta che dovresti usare "Dipende" è quando il tuo pacchetto è un componente aggiuntivo o un compagno di un altro pacchetto, in cui l'utente finale utilizzerà le funzioni sia del pacchetto sia del pacchetto "Dipende" nel loro codice. Se l'utente finale si interfaccia solo con le tue funzioni e l'altro pacchetto farà il lavoro solo dietro le quinte, usa invece "Imports".

L'avvertenza a questo è che se aggiungi un pacchetto a "Import", come di solito dovresti, il tuo codice dovrà fare riferimento alle funzioni di quel pacchetto, usando la sintassi completa dello spazio dei nomi, ad esempio dplyr::mutate(), anziché solo mutate(). Rende il codice un po 'più scomodo da leggere, ma è un piccolo prezzo da pagare per una migliore igiene del pacchetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.