Meilleure explication du moment où utiliser les importations / dépendants


148

Le manuel « Écriture d'extensions R » fournit les conseils suivants pour savoir quand utiliser Imports ou Depends:

Les règles générales sont

  • Les packages dont seul l'espace de noms est nécessaire pour charger le package à l'aide de la bibliothèque (pkgname) doivent être répertoriés dans le champ 'Imports' et non dans le champ 'Depends'.
  • Les packages qui doivent être attachés pour charger correctement le package à l'aide de la bibliothèque (pkgname) doivent être répertoriés dans le champ «Dépend» uniquement.

Quelqu'un peut-il fournir un peu plus de clarté à ce sujet? Comment savoir si mon package n'a besoin que d'espaces de noms chargés par rapport au moment où j'ai besoin d'un package à joindre? Quels sont des exemples des deux? Je pense que le package typique est juste une collection de fonctions qui appellent parfois des fonctions dans d'autres packages (où un peu de travail a déjà été codé). Ce scénario est-il 1 ou 2 ci-dessus?

Éditer

J'ai écrit un article de blog avec une section sur ce sujet spécifique (recherchez «Imports v Depends»). Les visuels le rendent beaucoup plus facile à comprendre.


1
Votre article de blog m'a tout dit sur la structure des packages, lorsque j'ai commencé à planifier des modules . Merci!
Konrad Rudolph le

Réponses:


143

"Imports"est plus sûr que "Depends"(et fait également d'un paquet qui l'utilise un «meilleur citoyen» par rapport aux autres paquets qui l'utilisent "Depends").

Une "Depends"directive tente de garantir qu'une fonction d'un autre package est disponible en attachant l'autre package au chemin de recherche principal (c'est-à-dire à la liste des environnements renvoyés par search()). Cette stratégie peut cependant être contrecarrée si un autre package, chargé plus tard, place une fonction de nom identique plus tôt sur le chemin de recherche. Chambers ( dans SoDA ) utilise l'exemple de la fonction "gam", qui se trouve à la fois dans les packages gamet mgcv. Si deux autres packages étaient chargés, l'un d'eux dépendant de gamet l'autre dépendant de mgcv, la fonction trouvée par les appels à gam()dépendrait de l'ordre dans lequel ces deux packages étaient attachés. Pas bon.

Une "Imports"directive doit être utilisée pour tout package de support dont les fonctions doivent être placées <imports:packageName>(recherchées immédiatement après <namespace:packageName>), au lieu de sur le chemin de recherche normal. Si l'un des packages de l'exemple ci-dessus utilisait le "Imports"mécanisme (qui requiert également importou des importFromdirectives dans le NAMESPACEfichier), les choses seraient améliorées de deux manières. (1) Le package prendrait lui-même le contrôle de la mgcvfonction utilisée. (2) En gardant le chemin de recherche principal dégagé des objets importés, cela ne casserait même pas potentiellement la dépendance de l'autre paquet sur l'autre mgcvfonction.

C'est pourquoi l'utilisation d'espaces de noms est une si bonne pratique, pourquoi elle est désormais appliquée par CRAN, et (en particulier) pourquoi l'utilisation "Imports"est plus sûre que l'utilisation "Depends".


Modifié pour ajouter une mise en garde importante:

Il y a une exception malheureusement courante au conseil ci-dessus: si votre paquet repose sur un paquet Aqui lui-même "Depends"sur un autre paquet B, votre paquet devra probablement être attaché Aavec une "Dependsdirective.

Cela est dû au fait que les fonctions du package Aont été écrites dans l'espoir que le package Bet ses fonctions seraient attachés au search()chemin .

Une "Depends"directive chargera et attachera le package A, à quel point Ala propre "Depends"directive du package provoquera, dans une réaction en chaîne, le chargement et l'attachement du package B. Les fonctions du package Apourront alors trouver les fonctions du package Bsur lesquelles elles reposent.

Une "Imports"directive chargera mais n'attachera pas le package Aet ne chargera ni n'attachera le package B. ( "Imports"après tout, s'attend à ce que les auteurs de packages utilisent le mécanisme d'espace de noms, et que ce package Autilisera "Imports"pour pointer vers toutes les fonctions Bauxquelles il a besoin d'accéder.) Les appels par vos fonctions à toutes les fonctions du package Aqui reposent sur des fonctions du package Bseront par conséquent échouer.

Les deux seules solutions sont soit:

  1. Demandez à votre package de joindre le package à l' Aaide d'une "Depends"directive.
  2. Mieux vaut à long terme, contactez le responsable du package Aet demandez-lui de faire un travail plus soigneux de construction de son espace de noms (selon les mots de Martin Morgan dans cette réponse connexe ).

1
Ayant récemment posé une question similaire et récemment lutté avec force avec ces problèmes, ce sont des concepts subtils et souvent mal communiqués. Je vous renvoie ici pour une autre explication: stackoverflow.com/questions/7880355/…
Bryan Hanson

@BryanHanson - Merci d'avoir rédigé les notes sur ce lien. Les différences entre les exigences de version Importset Dependswrt et la vérification des exemples dans les .Rdfichiers sont en effet subtiles et méritent d'être connues.
Josh O'Brien

1
La mise en garde concernant les dépendances qui utilisent «Depends» est une chose horrible. Cela signifie que je ne peux pas utiliser "Importations" dans mon package tant que tout le monde ne le fait pas. = (
Ken Williams

Une chose sur laquelle je ne suis toujours pas clair est que si j'écris un package et que je le souhaite Imports: ggplot2, pourquoi mon package ne trouve- autoplott- il pas la fonction? Attache évidemment Dependsla bibliothèque de packages de ggplot2et il n'y a donc pas de problème. par exemple j'ai une fonction autoplot.myFunction() qui utilise la @import ggplot2balise et mon paquet a Imports: ggplot2mais j'obtiens une erreur: Error in eval(expr, envir, enclos) : could not find function "autoplot"quand j'essaye de l'utiliser.
nathaneastwood

1
@Willem Merci. Vous avez bien sûr raison, et j'ai modifié la réponse pour clarifier le contenu trompeur. Une partie de ce qui a rendu cette réponse compliquée est que, tandis que le PO a formulé sa question en référence aux sections Dependset Importsde DESCRIPTION, il se demandait vraiment ce que signifie "importer" une fonction (plutôt que "dépendre" d'elle). Puisque cette dernière question est la question à laquelle j'ai tenté de répondre (et - je suppose - ce que la plupart des gens qui recherchent cette réponse veulent savoir), je laisserai la réponse inchangée.
Josh O'Brien

31

Hadley Wickham donne une explication simple ( http://r-pkgs.had.co.nz/namespace.html ):

Lister un package dans l'un Dependsou l' autre Importsgarantit qu'il est installé lorsque cela est nécessaire. La principale différence est que là où il Importssuffit de charger le paquet, Dependsil l'attache. Il n'y a pas d'autres différences. [...]

Sauf s'il y a une bonne raison pour le contraire, vous devriez toujours lister les paquets Importsnon Depends. En effet, un bon package est autonome et minimise les modifications de l'environnement global (y compris le chemin de recherche). La seule exception est si votre package est conçu pour être utilisé avec un autre package. Par exemple, le package analogique repose sur le végétalien. Ce n'est pas utile sans végétalien, donc il y a végétalien à la Dependsplace Imports. De même, ggplot2 devrait vraiment dépendre des échelles, plutôt que de l'importer.


15

Chambers dans SfDA dit d'utiliser «Imports» lorsque ce paquet utilise un mécanisme «d'espace de noms» et puisque tous les paquets doivent maintenant les avoir, alors la réponse pourrait maintenant être toujours utiliser «Imports». Dans le passé, les packages auraient pu être chargés sans réellement avoir d'espaces de noms et dans ce cas, vous auriez dû utiliser Depends.


2
lorsqu'un package est spécifié dans "importations" et que je souhaite utiliser une fonction dans le package, mes propres fonctions doivent-elles appeler la bibliothèque (...) ou toutes les fonctions sont-elles déjà disponibles dans le chemin de recherche? Aussi, qu'est-ce que SfDA? liens?
SFun28

2
Logiciel pour l'analyse des données : springer.com/statistics/computanional+statistics/book/… ... quant à vos questions, je ne connais pas la réponse par désinvolture, mais vous pourriez pirater un package de test minimal assez facilement et trouver la réponse empiriquement ...
Ben Bolker

1
SfDA == "Logiciel pour l'analyse des données". [65] sur r-project.org/doc/bib/R-books.html . Si un paquet spécifie un autre paquet, vous devriez voir un message vous informant du chargement des dépend (encies) et import (ations) lorsque vous utilisez soit library () soit require () sur la console. Oui, ils devraient alors être disponibles.
IRTFM du

4
+1 - C'est aussi ma forte impression. En outre, un package spécifié dans les importations sera recherché immédiatement après le <namespace:packageName>, dans le cadre de <imports:packageName>. Aucun autre appel à library()n'est nécessaire, et R ne vous avertira pas sur la console au moment du chargement du package à moins que le Importpackage ed ne puisse être trouvé.
Josh O'Brien

5

Voici une question simple pour vous aider à décider lequel utiliser:

Votre package nécessite-t-il que l' utilisateur final ait un accès direct aux fonctions d'un autre package?

  • NON -> Importations (réponse la plus courante)
  • OUI -> Dépend

Le seul moment où vous devriez utiliser "Depends" est lorsque votre package est un module complémentaire ou un compagnon d'un autre package, où votre utilisateur final utilisera les fonctions de votre package et du package "Depends" dans leur code. Si votre utilisateur final ne s'interfacera qu'avec vos fonctions et que l'autre package ne fonctionnera que dans les coulisses, utilisez à la place "Importations".

La mise en garde à ceci est que si vous ajoutez un package à 'Imports', comme vous le faites habituellement, votre code devra faire référence aux fonctions de ce package, en utilisant la syntaxe complète de l'espace de noms, par exemple dplyr::mutate(), au lieu de simplement mutate(). Cela rend le code un peu plus difficile à lire, mais c'est un petit prix à payer pour une meilleure hygiène des emballages.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.