2010-12-06 35 views
4

Je vois l'idiome suivant dans la fonction .First.lib dans un grand nombre de paquets R:idiome .First.lib en R paquets

fullName <- paste("package", pkgname, sep=":") 
myEnv <- as.environment(match(fullName, search())) 
barepackage <- sub("([^-]+)_.*", "\\1", pkgname) 
dbbase <- file.path(libname, pkgname, "R", barepackage) 
rm(.First.lib, envir = myEnv) 
lazyLoad(dbbase, myEnv) 
if(exists(".First.lib", envir = myEnv, inherits = FALSE)) { 
    f <- get(".First.lib", envir = myEnv, inherits = FALSE) 
    if(is.function(f)) 
     f(libname, pkgname) 
    else 
     stop(gettextf("package '%s' has a non-function '.First.lib'", 
         pkgname), 
      domain = NA) 
} 

Je comprends que la fonction .First.lib est exécutée lorsqu'un le paquet est chargé. Je comprends que le code ci-dessus définit un environnement pour le package et définit un chemin, mais je ne comprends pas pourquoi il recherche une fonction .First.lib après qu'il supprime explicitement la fonction .First.lib. Qu'est-ce qui rend l'idiome ci-dessus si commun? Est-ce une "meilleure pratique" d'inclure ceci dans un paquet R?

Répondre

11

Ce genre d'idiome est antique. Les paquets doivent avoir des espaces de noms et utiliser .onLoad, .onUnload et .onAttach. Par exemple:

.onLoad <- function(libname, pkgname){ 
    # do whatever needs to be done when the package is loaded 
    # some people use it to bombard users with 
    # messages using 
    packageStartupMessage("my package is so cool") 
    packageStartupMessage("so I will print these lines each time you load it") 
} 

L'entreprise whold avec l'appel de la fonction lazyload est préférable d'éviter en ajoutant simplement ceci au fichier DESCRIPTION:

LazyLoad: true 
3

Vous demandez pourquoi il cherche .First.Lib lorsque le script supprimé plus tôt. lazyLoad charge une base de données d'objets R, qui dans le code ci-dessus est chargé dans l'environnement myEnv. Il n'est pas inconcevable que l'ensemble des objets chargés dans cet environnement contienne un .First.Lib et c'est ce que le code recherche. En effet, je suppose que l'intention était de seulement exécuter le .First.Lib qui a été stocké dans la base de données objet chargé.

Un autre idiome commun dans des emballages sans NAMESPACE, est-ce (du paquet végétalien):

.First.lib <- function(lib, pkg) { 
    library.dynam("vegan", pkg, lib) 
    packageStartupMessage("This is vegan ", 
          utils::packageDescription("vegan", field="Version"), 
          appendLF = TRUE) 
} 

Cette charge le code compilé prêt à l'emploi et imprime un message simple de démarrage avec le nom du package et numéro de version. Ceci est similaire dans l'esprit au .onLoad de la réponse de @ Romain, mais sans le NAMESPACE.

+0

Il est très facile d'utiliser un NAMESPACE et c'est utile. Et ici, il vous donne useDynLib pour charger le code compilé –

+1

@Romain: Merci, oui. Je suis en train d'ajouter un NAMESPACE aux deux paquets que j'ai créés. La dernière fois que j'ai parlé avec le développeur principal de végétalien, il était complètement opposé à l'ajout d'un à l'emballage. Tandis que les fichiers NAMESPACE ne sont pas requis pour que les paquets réussissent la vérification R CMD, j'ai pensé qu'il valait la peine de documenter un '.First.lib' beaucoup plus simple que celui que @JD Long a montré dans son Q. –