2013-04-23 6 views
13

Sto tentando di generare classi di riferimento all'interno di un pacchetto R al volo e si sta dimostrando piuttosto difficile. Ecco gli approcci che ho seguito e i problemi che ho incontrato:Generazione dinamica classi di riferimento

Sto creando un pacchetto in cui spero di essere in grado di leggere dinamicamente uno schema e generare automaticamente una classe di riferimento associata (think SOAP) . Ovviamente, questo significa che non sarò in grado di definire le mie classi di riferimento prima mano nei sorgenti del pacchetto.

inizialmente ho cercato di creare una nuova classe con un semplice:

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

che, ovviamente, funziona bene quando eseguito in modo interattivo, ma quando incluso nelle fonti del pacchetto, ottengo un errore locked binding. Dalla mia lettura, sembra che questo si verifichi perché quando si esegue in modo interattivo, le informazioni sulla classe vengono archiviate nell'ambiente globale, che non è bloccato, mentre l'ambiente di base del mio pacchetto è bloccato.

Ho poi trovato un filo che ha suggerito di utilizzare qualcosa per l'effetto di:

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

Questo in realtà si è schiantato R/Studio quando ho cercato di creare il pacchetto, in modo da non avere un log dell'errore ha generato, sfortunatamente, ma certamente non ha funzionato.

Successivamente ho provato a creare un nuovo ambiente all'interno del mio pacchetto che potrei usare per memorizzare queste classi di riferimento. Così ho aggiunto una linea .classEnv <- new.env() nelle mie sorgenti di pacchetto (non all'interno di ogni funzione) e poi ha tentato di utilizzare questa classe quando si crea una nuova classe di riferimento:

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

Questo in realtà sembrava funzionare bene, ma genera il seguente avviso :

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

Così, per qualche ragione, methods::getPackageName() non è in grado di raccogliere quale pacchetto mio nuovo ambiente è in?

C'è un modo per creare il mio nuovo ambiente in modo diverso in modo che getPackageName() possa riconoscere correttamente il pacchetto? Posso aggiungere alcune funzionalità che mi consentono di aiutare lo getPackageName() a rilevare il pacchetto? Funzionerà anche se riuscirò a gestire l'avviso o sto abusando delle classi di riferimento provando a crearle dinamicamente?

+0

'? SetRefClass' dice che gli argomenti' ... 'sono passati a'? SetClass', e questo ha argomento 'pacchetto'; vuoi prendere il tuo terzo approccio, con argomento 'pacchetto = 'YourPackage'' o qualcosa del genere? –

+0

Grazie per il suggerimento, Martin. Sfortunatamente, non è stato possibile rimuovere l'errore. Sembra che il nome del pacchetto non rientri completamente in 'getPackageName' da cui proviene l'avviso se la variabile' .packageName' non è già stata specificata. –

risposta

5

Per avviare la conversazione, ho trovato che getpackageName memorizza il nome del pacchetto in una variabile nascosta .packageName nell'ambiente specificato.

Così si può effettivamente ottenere intorno al avviso con

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

che risolve l'avvertimento, ma la documentazione dice di non fidarsi variabile .packageName a tempo indeterminato, e mi sento ancora come se fossi l'hacking questo e maggio essere fraintendere qualcosa di importante sulle classi di riferimento e la loro relazione con gli ambienti.

i dettagli Da documentazione:

nomi dei package sono normalmente installati durante il caricamento del pacchetto, dallo script INSTALL o dalla funzione di libreria. (Attualmente, il nome è archiviato come oggetto .packageName ma non si fida di questo per il futuro.)


Edit:

Dopo aver letto un po 'più avanti, il metodo setPackageName può essere un modo più affidabile per impostare il nome del pacchetto per l'ambiente. Per i documenti:

setPackageName può essere utilizzato per stabilire un nome di pacchetto in un ambiente che altrimenti non ne avrebbe uno. Questo consente di creare classi e/o metodi in un ambiente arbitrario, ma di solito è preferibile creare pacchetti dagli strumenti standard di programmazione R (package.skeleton, etc.)

Quindi sembra che una valida soluzione sarebbe il seguente:

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

Questo elimina il messaggio di avviso e non si basa su nulla che sia documentato come instabile. Non sono ancora chiaro perché sia ​​necessario, ma ...