2013-02-14 13 views
21

Ho letto this basic question per rinominare gli oggetti e la risposta di @Shane ad esso, indicandomi una valutazione pigra. Ora mi chiedo se anche lo assign sia valutato pigramente. Proprio come qui:Lazy evaluation in R - viene assegnato l'errore?

assign("someNewName",someOldObject) 
rm(someOldObject) 

Il motivo per cui mi chiedo su questo è il seguente caso d'uso: Si supponga Ho 10K + R oggetti ognuno dei quali ha due attributi chiamati originalName e additionalName. Ora voglio scrivere una funzione che possa consentire all'utente di passare da un nome all'altro senza perdere questi due attributi. Più o meno così ...

EDIT: basato sull'input di @ Hadley ho cambiato il mio codice.

switchObjectName <- function(x) { 
    n1 <- attributes(x)$originalName 
    n2 <- attributes(x)$additionalName 
    objName <- deparse(substitute(x)) 
    if(objName == n1) { 
    delayedAssign(n2,x,assign.env=.GlobalEnv) 
    } else { 
    delayedAssign(n1,x,assign.env=.GlobalEnv) 
    } 
    rm(list=c(objName),envir=.GlobalEnv)  
} 

questo funziona bene, ma ho avuto un po 'di difficoltà per ottenere il giusto rm dichiarazione. Ho provato rm(objName,envir=.GlobalEnv) ma non riuscivo a farlo funzionare anche se objName è sicuramente un personaggio perché è il risultato di deparse(substitute(x).

+12

Se ho letto correttamente la tua domanda, consulta 'delayedAssign', https://github.com/hadley/pryr/blob/master/R/assign-delayed.r e la sezione" Assegnazione: nomi dei collegamenti ai valori "su https://github.com/hadley/devtools/wiki/environments – hadley

+0

grazie ancora una volta. in particolare quel puntatore al capitolo nella tua wiki ha aiutato molto a capire cosa sta realmente accadendo. 'delayedAssign' era davvero il suggerimento giusto. –

risposta

5

La lingua R in genere ha la semantica valore. L'assegnazione x <- y significa che x e saranno copie indipendenti dello stesso oggetto (gli aggiornamenti su e x saranno indipendenti). Un'implementazione ingenua di x <- y allocherà sempre memoria per x e copierà completamente . GNU-R utilizza invece un meccanismo di copia su scrittura, rimanderebbe la copia fino a quando non si verifica effettivamente un aggiornamento, che salva la memoria/tempo di esecuzione nel caso in cui non si verifichi. Gli utenti R non devono conoscere questa ottimizzazione, è completamente trasparente (tranne alcuni rari casi come errori di memoria insufficiente). Questo meccanismo si applica alle assegnazioni scritte come x <- y e assign("x", y) allo stesso modo.

Valutazione lenta è parte del design della lingua ed è visibile agli utenti R/programmatori. Le espressioni passate come argomenti a una funzione, ad es. in foo(ls()) l'espressione passata è ls(), viene valutata pigramente, solo se e quando necessario dall'implementazione della funzione chiamata.

delayedAssign è una funzione di basso livello, visibile per utenti R/programmatori, ma in realtà viene utilizzata solo per il caricamento lento dei pacchetti e non dovrebbe essere necessaria nei programmi utente. delayedAssign consente di specificare un'espressione per calcolare il valore di una variabile; il calcolo avverrà pigramente solo se/quando la variabile viene letta la prima volta.

Quindi, per rispondere alla domanda, un incarico in R è sempre "pigro" in quanto viene utilizzato il meccanismo di copia su scrittura. Il calcolo del lato destro del compito può essere anche pigro (usando delayedAssign), ma questo non dovrebbe essere necessario/utilizzato dai programmi utente.

Penso che per la "rinomina" delle variabili, non è necessario utilizzare delayedAssign (perché il lato destro non è calcolato). Rende la situazione solo più complessa e ci sarà probabilmente un sovraccarico delle prestazioni dovuto alla contabilità che deve fare delayedAssign. Vorrei solo usare il compito ordinario se dovessi rinominare le variabili.

Per chiarezza del codice, vorrei anche quando possibile provare a evitare l'eliminazione di variabili dagli ambienti e persino l'assegnazione di una funzione nell'ambiente globale, ad es. Vorrei solo creare una nuova lista e inserire le nuove associazioni (variabili) in essa.

Avendo menzionato il meccanismo copy-on-write, con l'implementazione corrente in GNU-R, qualsiasi soluzione descritta potrebbe causare la copia di memoria che non sarebbe necessaria se le variabili non fossero state ridenominate. Non c'è modo di evitarlo a livello R.

Problemi correlati