2010-07-16 10 views
26

Nel "Qual è il trucco R più utile?" (here), ho letto che l'uso degli ambienti fornisce "capacità di riferimento pass-by". Ci sono limiti e/o trucchi con questo approccio?In quali casi si dovrebbe utilizzare new.env per creare un nuovo ambiente?

Inoltre, in generale quali sono i pro e i contro dell'uso di ambienti creati? Questo è qualcosa su cui sono stato confuso da un po 'di tempo, quindi qualsiasi chiarimento o riferimento mi sarebbe stato molto utile.

Grazie in anticipo.

+0

Questo può essere nodale ed è sicuramente oltre lo scopo di ciò che è necessario per un utente R "standard" ('install.packages' + importare dati + eseguire test statistici su' data.frame's). Ma per compiti spiacevoli, a volte penso a 'new.env' come creare un puntatore. Se volessi emulare un C 'struct', lo farei con una sequenza di' new.env' nidificati. – isomorphismes

+0

È inoltre possibile eseguire [multi-assegnazione] (https://stat.ethz.ch/R-manual/R-devel/library/base/html/list2env.html) con gli ambienti. (Una caratteristica presumibilmente mancante che ad esempio Pythonistas a volte si lamenta.) – isomorphismes

risposta

28

Mentre sono d'accordo con la consulenza globale di Harlan (cioè non usare qualcosa a meno che non lo si capisce), vorrei aggiungere:

ambienti sono un fondamentale concetto in R, ed a mio avviso, estremamente utile (in altre parole: valgono la pena di capire!). Gli ambienti sono molto importanti per comprendere le problematiche relative all'ambito. Alcune cose basilari che dovresti capire in questo contesto:

  1. search(): ti mostrerà l'area di lavoro; gli ambienti sono elencati in ordine di priorità. L'ambiente principale è. GlobalEnv e può sempre essere referenziato come tale.
  2. ls(): vi mostrerà ciò che è contenuto in un ambiente
  3. attach/detach: crea un nuovo ambiente per un oggetto
  4. get, assign, <<-, e <-: si dovrebbe sapere la differenza tra queste funzioni
  5. with: un metodo per lavorare con un ambiente senza collegarlo.

Un altro puntatore: uno sguardo al the proto package (usato in ggplot), che utilizza per fornire ambienti eredità controllata.

Infine, vorrei sottolineare che gli ambienti sono molto simili alle liste: possono sia archiviare qualsiasi tipo di oggetto al loro interno (vedere this question). Ma a seconda del tuo caso d'uso (ad esempio vuoi occuparti di ereditarietà e priorità), una lista può essere più facile da gestire. E puoi sempre attach un elenco come un ambiente.

Edit: Se volete vedere un esempio di proto al lavoro in ggplot, avere uno sguardo che la struttura di un oggetto ggplot, che è essenzialmente una lista composta in parte di ambienti:

> p <- qplot(1:10, 1:10) 
> str(p) 
List of 8 
$ data  :'data.frame': 0 obs. of 0 variables 
$ layers  :List of 1 
    ..$ :proto object 
.. .. $ legend  : logi NA 
.. .. $ inherit.aes: logi TRUE 
... 
> class(p$layers[[1]]) 
[1] "proto"  "environment" 
> is.environment(p$layers[[1]]) 
[1] TRUE 

Nota come è stato costruito usando proto e come risultato contiene molti ambienti. È inoltre possibile tracciare le relazioni in questi oggetti utilizzando graph.proto.

+0

Spero di capirli in modo che io possa usarli potenzialmente. Ho una certa familiarità con le regole di scoping in R e con la maggior parte delle funzioni che hai elencato, ma esplorerò i dettagli in modo più approfondito. Grazie per le informazioni. – ramhiser

+3

Completamente d'accordo, Shane! È importante comprendere gli ambienti e l'ambito in R se si sta costruendo una quantità significativa di codice! Ma questo non implica necessariamente che dovresti usare gli ambienti come strutture di dati. – Harlan

+2

@Harlan: Sono completamente d'accordo. Forse dovrei essere più deciso su quel fronte. @ John: non utilizzare gli ambienti a meno che tu (1) li comprenda e (2) abbia una buona ragione per farlo. Una lista è generalmente un'opzione migliore. IMO, è una buona pratica evitare gli effetti collaterali a meno che tu non sia assolutamente impossibile! – Shane

5

Bene, se non li capisci e le persone che potresti dover leggere il tuo codice (compreso il tuo futuro io) non capiscono gli ambienti, quindi non dovresti usarli! Sono stati progettati per essere utilizzati per incapsulare gli spazi dei nomi nei pacchetti e così via. Il fatto che sia possibile utilizzare per pass-per-riferimento e tabelle hash non significa necessariamente che deve essere. È un trucco In generale, l'uso di deep magic non è consigliabile, anche se rende il codice un po 'più veloce.

+1

Quindi ogni volta che trovo un nuovo trucco, dovrei evitarlo perché non lo capisco? Spesso eseguo operazioni su matrici di covarianza di grandi dimensioni passandole da una funzione all'altra. L'utilizzo di ambienti migliorerebbe le prestazioni in questa situazione abbastanza da giustificarne l'utilizzo? – ramhiser

+0

Non sono completamente sicuro dei dettagli di implementazione, ma credo che se non si modificano le matrici di grandi dimensioni all'interno delle funzioni, non vengono effettivamente copiate. Per quanto riguarda la tua domanda più ampia, ti consiglio che se hai bisogno della velocità, può valere la pena di imparare la magia, tieni presente che si tratta di un (lieve) abuso della semantica dei linguaggi per farlo, e che potresti pentirtene dopo. O forse non te ne pentirai! – Harlan

+4

+1 Per toccare le preoccupazioni di Harlan: sì, questo è un uso pericoloso perché introduce "effetti collaterali". Ogni volta che consenti a una funzione di modificare il mondo esterno, ti stai aprendo a un comportamento inaspettato. http://en.wikipedia.org/wiki/Side_effect_(computer_science) – Shane

Problemi correlati