2013-04-23 14 views
13

Próbuję generować klasy referencyjne w pakiecie R w locie, a to okazuje się dość trudne. Oto podejścia, które podjąłem i problemy, na które natrafiłem:Dynamicznie generuj klasy referencyjne

Tworzę pakiet, w którym mam nadzieję, że będę w stanie dynamicznie odczytywać w schemacie i automatycznie generować skojarzoną klasę odniesienia (pomyśl o SOAP) . Oczywiście oznacza to, że nie będę w stanie zdefiniować moich klas referencyjnych z wyprzedzeniem w źródłach pakietów.

początkowo próbowali stworzyć nową klasę za pomocą prostego:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character")) 

które, oczywiście, działa bez zarzutu, gdy wykonywane interaktywnie, ale gdy są zawarte w źródłach pakietu, pojawia się błąd locked binding. Z mojego czytania wynika, że ​​tak się dzieje, ponieważ podczas interaktywnego działania informacje o klasie są przechowywane w środowisku globalnym, które nie jest zablokowane, podczas gdy środowisko podstawowe mojego pakietu jest zablokowane.

I wtedy okazało się, że wątek sugerowany użyciu coś do skutku:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=globalenv()) 

To rzeczywiście rozbił R/Studio kiedy próbowałem zbudować pakiet, więc nie mam dziennik błędu wygenerował, niestety, ale z pewnością nie działał.

Następnie próbowałem stworzyć nowe środowisko w moim pakiecie, które mógłbym użyć do przechowywania tych klas referencyjnych. Więc dodałem .classEnv <- new.env() linię w moich źródeł pakietów (nie wewnątrz jakiejkolwiek funkcji), a następnie próbował użyć tej klasy podczas tworzenia nowej klasy odniesienie:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=.classEnv) 

To rzeczywiście wydawało się działać OK, ale generuje następujące ostrzeżenie :

> myClass <- setRefClass("NewClassName", where=.classEnv) 
Warning message: 
In getPackageName(where) : 
    Created a package name, ‘2013-04-23 10:19:14’, when none found 

Tak, z jakiegoś powodu, methods::getPackageName() nie jest w stanie odebrać mój nowy pakiet, który znajduje się w otoczenie?

Czy istnieje sposób na stworzenie nowego środowiska w inny sposób, aby getPackageName() mógł poprawnie rozpoznać pakiet? Czy mogę dodać funkcję, która pozwala mi wykryć pakiet? Czy zadziała to nawet, jeśli potrafię poradzić sobie z ostrzeżeniem, czy też niewłaściwie używam klas referencyjnych, próbując tworzyć je dynamicznie?

+0

'setRefClass' twierdzi, że argumenty' ... '' są przekazywane do setClass', a to ma argumentu 'package'?; czy chcesz przyjąć swoje trzecie podejście, z argumentem 'package = 'YourPackage'' lub coś podobnego? –

+0

Dzięki za cynk, Martin. Niestety nie udało się usunąć błędu. Wygląda na to nazwa pakietu nie sączyć całą drogę w dół do 'getPackageName' czyli tam, gdzie ostrzeżenie pochodzi z' jeśli zmienna .packageName' nie został jeszcze określony. –

Odpowiedz

5

Aby nawiązać rozmowę, znalazłem, że getpackageName przechowuje nazwę pakietu w ukrytej zmiennej .packageName w określonym środowisku.

Więc rzeczywiście można obejść ostrzeżenia z

assign(".packageName", "MyPkg", envir=.classEnv)  
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv) 

który rozwiązuje ostrzeżenia, ale dokumentacja nie mówi zaufać zmienną .packageName nieskończoność, a ja wciąż czuję się jak hacking to i może być niezrozumieniem czegoś ważnego na temat klas referencyjnych i ich związku ze środowiskiem.

Pełne dane z dokumentacji:

Nazwy pakietów są zwykle instalowane podczas ładowania pakietu, przez skrypt zainstalować lub przez funkcję biblioteki. (Obecnie nazwa jest przechowywana jako obiekt .packageName, ale nie ufaj temu w przyszłości.)


Edit:

Po przeczytaniu trochę dalej, metoda setPackageName może być bardziej niezawodny sposób, aby ustawić nazwę pakietu dla środowiska. Na dokumenty:

setPackageName może być użyty do ustalenia nazwy pakietu w środowisku, które w innym przypadku nie miałoby takiego pakietu. Umożliwia to tworzenie klas i/lub metod w dowolnym środowisku, ale zwykle lepiej jest tworzyć pakiety za pomocą standardowych narzędzi programistycznych R (package.skeleton, itp.).

Wygląda na to, że jedno prawidłowe rozwiązanie byłby następujący:

setPackageName("MyPkg", .classEnv) 
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv) 

To eliminuje ostrzeżenie i nie polega na niczym, co jest udokumentowane jako niestabilne. Nadal nie jestem jasne, dlaczego jest to konieczne, ale ...

Powiązane problemy