2015-06-11 6 views
6

Attualmente sto lavorando a un pacchetto R e sto provando a seguire le linee guida sulle best practice fornite da Hadley Wickham a http://r-pkgs.had.co.nz. Come parte di questo, ho l'obiettivo di avere tutte le dipendenze del pacchetto all'interno della sezione Imports del file DESCRIPTION piuttosto che il Depends poiché sono d'accordo con la filosofia di non alterare inutilmente l'ambiente globale (qualcosa che molti pacchetti CRAN e Bioconductor don sembra che seguano).Come utilizzare i metodi S3 da un altro pacchetto che utilizza l'esportazione anziché S3method nel suo spazio dei nomi senza utilizzare Depends o library()

Desidero utilizzare le funzioni all'interno del pacchetto Bioconductor rhdf5 all'interno di una delle mie funzioni pacchetto, in particolare h5write(). Il problema che ho ora incontrato è che non ha i suoi metodi S3 dichiarati come tali nel suo NAMESPACE. Essi vengono dichiarate utilizzando (es)

export(h5write.default) 
export(h5writeDataset.matrix) 

anziché

S3method(h5write, default) 
S3method(h5writeDataset, matrix) 

La h5write generico è definito come:

h5write <- function(obj, file, name, ...) { 
res <- UseMethod("h5write") 
    invisible(res) 
} 

In pratica, ciò significa che invita a rhdf5 :: h5write sicuro perché non esiste un metodo h5write appropriato registrato.

Per quanto posso vedere, ci sono tre soluzioni a questo:

  1. Usa Depends piuttosto che Imports nel file di descrizione.
  2. Utilizzare library("rhdf5") o require("rhdf5") nel codice per la funzione pertinente.
  3. Modificare il file NAMESPACE per rhdf5 per utilizzare S3methods() anziché export().

Tutti questi hanno degli svantaggi. L'opzione 1 indica che il pacchetto viene caricato e collegato all'ambiente globale anche se la funzione pertinente nel mio pacchetto non viene mai chiamata. L'opzione 2 indica l'uso di library in un pacchetto, che mentre ancora unge il pacchetto all'ambiente globale ed è anche deprecato secondo le linee guida di Hadley Wickham. L'opzione 3 significherebbe affidarsi all'autore del pacchetto per aggiornare il pacchetto su Bioconductor e significa anche che i metodi S3 non vengono più esportati e che potrebbero a loro volta interrompere altri pacchetti che si basano su chiamarli esplicitamente.

Ho perso un'altra alternativa? Ho cercato altrove su StackOverflow e ho trovato le seguenti domande rilevanti Importing S3 method from another package e How to export S3 method so it is available in namespace? ma nulla che riguardasse direttamente il mio problema. Di nota, la differenza chiave rispetto al primo di questi due è che il generico e il metodo sono entrambi nello stesso pacchetto, ma il problema è l'uso di export anziché S3method.

codice di esempio per riprodurre l'errore (senza la necessità di creare un pacchetto):

loadNamespace("rhdf5") 
rdhf5::h5write(1:4, "test.h5", "test") 

Error in UseMethod("h5write") : 
no applicable method for 'h5write' applied to an object of class 
"c('integer', 'numeric') 

alternativa, c'è un pacchetto di scheletro a https://github.com/NikNakk/s3issuedemo che fornisce una singola funzione demonstrateIssue() che riproduce il messaggio di errore. Può essere installato utilizzando devtools::install_github("NikNakk/s3issuedemo").

+0

Non sono sicuro di quale sia la tua domanda esatta, stai cercando di utilizzare i metodi dei pacchetti? Stai cercando di creare nuovi metodi? Qual è il tuo obiettivo? La tua domanda è dettagliata ma non è molto chiara. – cdeterman

+0

Scusate se non ero chiaro. Voglio usare la funzione rhdf5 :: h5write all'interno di una funzione nel mio pacchetto. Tutto funziona bene se allego il pacchetto rhdf5 all'ambiente globale usando 'Depends' o' library() '. Funziona bene anche se altero il file NAMESPACE dell'altro pacchetto per usare 'S3method()' piuttosto che 'export()'. Altrimenti, fallisce. Ho modificato la mia domanda sopra. –

+0

Potete fornire un esempio riproducibile? Questo pacchetto è su github dove potremmo vedere il tuo codice sorgente? – cdeterman

risposta

6

La chiave qui è di importare i metodi specifici oltre al generico che si desidera utilizzare.Ecco come puoi farlo funzionare per il metodo predefinito.

Nota: si presume che il file test.h5 esista già.

#' @importFrom rhdf5 h5write.default 
#' @importFrom rhdf5 h5write 
#' @export 
myFun <- function(){ 
    h5write(1:4, "test.h5", "test") 
} 

Inoltre ho messo il mio piccolo pacchetto dimostrando questo here.

+0

Mille grazie. Questo risolve il problema. –

Problemi correlati