2015-06-11 6 views
6

Pracuję obecnie nad pakietem R i staram się postępować zgodnie z wytycznymi dotyczącymi najlepszych praktyk dostarczonymi przez Hadleya Wickhama na stronie http://r-pkgs.had.co.nz. W związku z tym zamierzam mieć wszystkie zależności od pakietu w sekcji Imports pliku DESCRIPTION, a nie Depends, ponieważ zgadzam się z filozofią niepotrzebnego zmieniania globalnego środowiska (coś, co wiele pakietów CRAN i Bioconductor don zdaje się iść za).Jak używać metod S3 z innego pakietu, który używa formatu eksportu zamiast S3method w swojej przestrzeni nazw bez użycia Depends lub biblioteki()

Chcę używać funkcji w pakiecie Biofonductor rhdf5 w ramach jednej z funkcji pakietu, w szczególności h5write(). Problem, na który teraz natknąłem, polega na tym, że nie ma on swoich metod S3 zadeklarowanych jako takie w NAMESPACE. Są one uznane za pomocą (np)

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

zamiast

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

Ogólny h5write jest zdefiniowany jako:

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

W praktyce oznacza to, że zwraca się do rhdf5 :: h5write zawieść ponieważ nie zarejestrowano odpowiedniej metody h5write.

O ile widzę, istnieją trzy rozwiązania to:

  1. Zastosowanie Depends zamiast Imports w pliku opisu.
  2. Użyj library("rhdf5") lub require("rhdf5") w kodzie odpowiedniej funkcji.
  3. Zmień plik NAMESPACE dla rhdf5, aby używać S3methods() zamiast export().

Wszystkie z nich mają wady. Opcja 1 oznacza, że ​​pakiet jest ładowany i dołączany do globalnego środowiska, nawet jeśli odpowiednia funkcja w moim pakiecie nigdy nie jest wywoływana. Opcja 2 oznacza użycie pakietu library w pakiecie, który ponownie dołącza pakiet do środowiska globalnego i jest również przestarzały zgodnie z wytycznymi Hadley Wickham. Opcja 3 oznaczałaby poleganie na tym, że inny autor pakietu zaktualizował swój pakiet na Bioconductor, a także oznaczał, że metody S3 nie są już eksportowane, co z kolei może złamać inne pakiety, które polegają na ich jawnym wywołaniu.

Czy przegapiłem inną alternatywę? Sprawdziłem gdzieś w StackOverflow i znalazłem następujące pytania: Importing S3 method from another package i How to export S3 method so it is available in namespace? nic, co bezpośrednio rozwiązuje mój problem. Warto zauważyć, że kluczową różnicą w stosunku do pierwszego z nich jest to, że rodzajowy i metoda znajdują się w tym samym pakiecie, ale problemem jest użycie raczej export niż S3method.

kodu do odtworzenia próbki błędu (bez konieczności tworzenia pakietu)

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') 

Alternatywnie można pakiet szkielet w https://github.com/NikNakk/s3issuedemo który stanowi pojedynczą funkcję demonstrateIssue() który odtwarza komunikat. Można go zainstalować przy użyciu devtools::install_github("NikNakk/s3issuedemo").

+0

Nie jestem pewien, jakie jest twoje dokładne pytanie, czy próbujesz użyć metod pakietów? Próbujesz tworzyć nowe metody? Jaki jest twój cel? Twoje pytanie jest szczegółowe, ale nie jest zbyt jasne. – cdeterman

+0

Przepraszam, jeśli nie byłam jasna. Chcę użyć funkcji rhdf5 :: h5write w funkcji w moim pakiecie. Wszystko działa dobrze, jeśli dołączę pakiet rhdf5 do środowiska globalnego za pomocą 'Depends' lub' library() '. Działa również dobrze, jeśli zmienię plik NAMESPACE innego pakietu, aby używał 'S3method()' zamiast 'export()'. Ale w przeciwnym razie zawodzi. Poprawiłem moje pytanie powyżej. –

+0

Czy możesz podać odtwarzalny przykład? Czy to twój pakiet na Github, gdzie mogliśmy zobaczyć twój kod źródłowy? – cdeterman

Odpowiedz

6

Kluczem jest tutaj zaimportowanie określonych metod oprócz ogólnego, którego chcesz użyć.Oto, jak możesz go uruchomić, aby działał domyślnie.

Uwaga: zakłada to, że plik test.h5 już istnieje.

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

Podaję również mój mały pakiet demonstrujący to here.

+0

Wielkie dzięki. To rozwiązuje problem. –

Powiązane problemy