Mejor explicación de cuándo usar Importaciones / Depende

148

El manual " Escritura de extensiones R " proporciona la siguiente guía sobre cuándo usar Importaciones o Depende:

Las reglas generales son

  • Los paquetes cuyo espacio de nombres solo es necesario para cargar el paquete usando la biblioteca (pkgname) deben aparecer en el campo 'Importaciones' y no en el campo 'Depende'.
  • Los paquetes que deben adjuntarse para cargar con éxito el paquete usando la biblioteca (pkgname) solo deben aparecer en el campo 'Depende'.

¿Alguien puede proporcionar un poco más de claridad sobre esto? ¿Cómo sé cuándo mi paquete solo necesita espacios de nombres cargados y cuándo necesito adjuntar un paquete? ¿Cuáles son ejemplos de ambos? Creo que el paquete típico es solo una colección de funciones que a veces llaman funciones en otros paquetes (donde ya se ha codificado un poco de trabajo). ¿Es este escenario 1 o 2 arriba?

Editar

Escribí una publicación de blog con una sección sobre este tema específico (busque 'Importaciones v Depende'). Las imágenes hacen que sea mucho más fácil de entender.

SFun28
fuente
1
Su publicación de blog me dijo todo sobre la estructura del paquete, cuando comencé a planificar módulos . ¡Gracias!
Konrad Rudolph

Respuestas:

143

"Imports"es más seguro que "Depends"(y también hace que un paquete lo use como un "mejor ciudadano" con respecto a otros paquetes que sí lo usan "Depends").

Una "Depends"directiva intenta asegurar que una función de otro paquete esté disponible adjuntando el otro paquete a la ruta de búsqueda principal (es decir, la lista de entornos devueltos por search()). Sin embargo, esta estrategia se puede frustrar si otro paquete, cargado más tarde, coloca una función con un nombre idéntico anteriormente en la ruta de búsqueda. Chambers ( en SoDA ) utiliza el ejemplo de la función "gam", que se encuentra en los paquetes gamy mgcv. Si se cargaron otros dos paquetes, uno de los cuales depende gamy el otro depende de mgcv, la función encontrada por las llamadas a gam()dependería del orden en que se adjuntaron esos dos paquetes. No está bien.

Se "Imports"debe usar una directiva para cualquier paquete de soporte cuyas funciones se deben colocar <imports:packageName>(buscar inmediatamente después <namespace:packageName>), en lugar de en la ruta de búsqueda normal. Si cualquiera de los paquetes en el ejemplo anterior usara el "Imports"mecanismo (que también requiere importo importFromdirectivas en el NAMESPACEarchivo), las cosas mejorarían de dos maneras. (1) El paquete en sí mismo obtendría el control sobre qué mgcvfunción se utiliza. (2) Al mantener la ruta de búsqueda principal libre de los objetos importados, ni siquiera rompería la dependencia del otro paquete de la otra mgcvfunción.

Esta es la razón por la cual el uso de espacios de nombres es una buena práctica, por qué ahora CRAN lo aplica y (en particular) por qué usar "Imports"es más seguro que usarlo "Depends".


Editado para agregar una advertencia importante:

Desafortunadamente, hay una excepción común a los consejos anteriores: si su paquete se basa en un paquete Aque se encuentra "Depends"en otro paquete B, es probable que deba adjuntarlo Acon una "Dependsdirectiva.

Esto se debe a que las funciones del paquete Ase escribieron con la expectativa de que el paquete By sus funciones se adjuntarían a la search()ruta .

Una "Depends"directiva cargará y adjuntará el paquete A, en cuyo punto Ala propia "Depends"directiva del paquete , en una reacción en cadena, hará que el paquete también Bse cargue y se adjunte. Las funciones en el paquete Apodrán encontrar las funciones en el paquete Ben las que se basan.

Una "Imports"directiva cargará pero no adjuntará el paquete Ay no cargará ni adjuntará el paquete B. ( "Imports"Después de todo, espera que los escritores de paquetes están utilizando el mecanismo de espacio de nombres, y que el paquete Ava a utilizar "Imports"hasta el punto de que cualquiera de las funciones en Bque necesitan tener acceso a.) Llama por sus funciones a cualquier función en el paquete Aque se basan en funciones en el paquete Bvoluntad en consecuencia fracasan.

Las dos únicas soluciones son:

  1. Haga que su paquete adjunte el paquete Ausando una "Depends"directiva.
  2. Mejor a largo plazo, comuníquese con el responsable del paquete Ay pídales que hagan un trabajo más cuidadoso al construir su espacio de nombres (en palabras de Martin Morgan en esta respuesta relacionada ).
Josh O'Brien
fuente
1
Habiendo formulado una pregunta similar recientemente y recientemente luchó poderosamente con estos problemas, estos son conceptos sutiles y a menudo mal comunicados. Lo remitiré aquí para otra explicación: stackoverflow.com/questions/7880355/…
Bryan Hanson
@BryanHanson - Gracias por escribir las notas en ese enlace. Las diferencias entre los requisitos de versión Importsy Dependswrt y la comprobación de ejemplos en .Rdarchivos son realmente sutiles y vale la pena conocerlas.
Josh O'Brien
1
La advertencia sobre las dependencias que usan 'Depends' es algo horrible. Significa que básicamente no puedo usar 'Importaciones' en mi paquete hasta que todos los demás también lo estén. = (
Ken Williams
Una cosa sobre la que aún no estoy claro es, si estoy escribiendo un paquete y quiero hacerlo Imports: ggplot2, ¿por qué mi paquete no encuentra la autoplotfunción? Obviamente Dependsadjunta la biblioteca de paquetes de ggplot2y, por lo tanto, no hay problema. Por ejemplo, tengo una función autoplot.myFunction() que usa la @import ggplot2etiqueta y mi paquete tiene Imports: ggplot2pero recibo un error: Error in eval(expr, envir, enclos) : could not find function "autoplot"cuando trato de usarla.
nathaneastwood
1
@Willem Gracias. Por supuesto, tiene razón, y he editado la respuesta para aclarar el contenido engañoso. Parte de lo que hizo que esta respuesta fuera complicada es que, aunque el OP formuló su pregunta con referencia a las secciones Dependsy , realmente estaba preguntando qué significa "importar" una función (en lugar de "depender" de ella). Como esa última es la pregunta que intenté responder (y, sospecho, lo que la mayoría de las personas que buscan esta respuesta quieren saber), dejaré la respuesta sin cambios. ImportsDESCRIPTION
Josh O'Brien
31

Hadley Wickham da una explicación fácil ( http://r-pkgs.had.co.nz/namespace.html ):

Enumerar un paquete en Dependso Importsasegura que se instala cuando sea necesario. La principal diferencia es que donde Importssolo carga el paquete, lo Dependsadjunta. No hay otras diferencias. [...]

A menos que haya una buena razón de lo contrario, siempre debe enumerar los paquetes en Importsnot Depends. Esto se debe a que un buen paquete es autónomo y minimiza los cambios en el entorno global (incluida la ruta de búsqueda). La única excepción es si su paquete está diseñado para usarse junto con otro paquete. Por ejemplo, el paquete analógico se basa en vegano. No es útil sin vegan, por lo que tiene vegan en Dependslugar de Imports. Del mismo modo, ggplot2 realmente debería depender de escalas, en lugar de importarlo.

majom
fuente
15

Chambers en SfDA dice que use 'Importaciones' cuando este paquete usa un mecanismo de 'espacio de nombres' y dado que ahora se requiere que todos los paquetes los tengan, entonces la respuesta podría ser siempre usar 'Importaciones'. En el pasado, los paquetes podrían haberse cargado sin tener espacios de nombres y, en ese caso, debería haber utilizado Depends.

IRTFM
fuente
2
cuando un paquete se especifica en "importaciones" y quiero usar una función en el paquete, ¿mis propias funciones necesitan llamar a la biblioteca (...) o todas las funciones ya están disponibles en la ruta de búsqueda? Además, ¿qué es SfDA? ¿Enlaces?
SFun28
2
Software para análisis de datos : springer.com/statistics/computanional+statistics/book/… ... en cuanto a sus preguntas, no sé la respuesta de antemano, pero podría hackear un paquete de prueba mínimo con bastante facilidad y encontrar la respuesta empíricamente ...
Ben Bolker
1
SfDA == "Software para análisis de datos". [65] en r-project.org/doc/bib/R-books.html . Si un paquete especifica otro paquete, debería ver un mensaje que le informa sobre la carga de depend (encies) e import (ations) cuando utiliza la biblioteca () o require () en la consola. Sí, entonces deberían estar disponibles.
IRTFM
44
+1 - Esta es mi fuerte impresión también. Además, se buscará un paquete especificado en las importaciones inmediatamente después de <namespace:packageName>, como parte de <imports:packageName>. No library()es necesario llamar más y R no lo notificará en la consola en el momento de la carga del paquete a menos que Importno se pueda encontrar el paquete ed.
Josh O'Brien
5

Aquí hay una pregunta simple para ayudarlo a decidir cuál usar:

¿Su paquete requiere que el usuario final tenga acceso directo a las funciones de otro paquete?

  • NO -> Importaciones (respuesta más común)
  • SÍ -> Depende

El único momento en que debe usar 'Depends' es cuando su paquete es un complemento o compañero de otro paquete, donde su usuario final utilizará funciones de su paquete y del paquete 'Depends' en su código. Si su usuario final solo interactuará con sus funciones, y el otro paquete solo estará trabajando detrás de escena, entonces use 'Importaciones' en su lugar.

La advertencia a esto es que si agrega un paquete a 'Importaciones', como debería hacerlo normalmente, su código deberá referirse a las funciones de ese paquete, utilizando la sintaxis completa del espacio de nombres, por ejemplo dplyr::mutate(), en lugar de solo mutate(). Hace que el código sea un poco más complicado de leer, pero es un pequeño precio a pagar por una mejor higiene del paquete.

Aaron Cooley
fuente