2010-07-16 11 views
26

En el "¿Cuál es el truco R más útil?" (here), leí que el uso de entornos proporciona "capacidades de paso por referencia". ¿Hay algún límite y/o problema con este enfoque?¿En qué casos se debe usar new.env para crear un nuevo entorno?

Además, en general, ¿cuáles son los pros y los contras del uso de entornos creados? Esto es algo de lo que he estado confundido por bastante tiempo, por lo que cualquier aclaración o referencia sería muy útil para mí.

Gracias de antemano.

+0

Esto puede ser complicado y seguramente está más allá del alcance de lo que se necesita para un usuario R "estándar" ('install.packages' + importar datos + ejecutar pruebas estadísticas en' data.frame's). Pero para tareas difíciles, a veces pienso en 'new.env' como crear un puntero. Si quisiera emular una C 'struct', lo haría con una secuencia de' new.env' anidada. – isomorphismes

+0

También puede hacer [multi-assign] (https://stat.ethz.ch/R-manual/R-devel/library/base/html/list2env.html) con entornos. (Una característica supuestamente faltante de la cual, por ejemplo, los Pythonistas a veces se quejan). – isomorphismes

Respuesta

28

Aunque estoy de acuerdo con el consejo general de Harlan (es decir, no usar algo menos que lo entienda), yo añadiría:

Los entornos son un elemento fundamental concepto en I, y en mi opinión, extremadamente útil (en otras palabras: ¡valen la pena entenderlo!). Los entornos son muy importantes para comprender los problemas relacionados con el alcance. Algunas cosas básicas que usted debe entender en este contexto:

  1. search(): le mostrará el espacio de trabajo; los entornos se enumeran por orden de prioridad. El entorno principal es .GlobalEnv, y siempre se puede referenciar como tal.
  2. ls(): le mostrará lo que está contenido en un entorno
  3. attach/detach: crea un nuevo entorno para un objeto
  4. get, assign, <<- y <-: usted debe saber la diferencia entre estas funciones
  5. with: un método para trabajar con un entorno sin asociarlo.

Otro puntero: echar un vistazo a the proto package (utilizado en ggplot), que utiliza entornos para proporcionar una herencia controlada.

Por último, quisiera señalar que los entornos son muy similares a las listas: ambos pueden almacenar cualquier tipo de objeto dentro de ellos (ver this question). Pero dependiendo de su caso de uso (por ejemplo, si desea lidiar con la herencia y la prioridad), una lista puede ser más fácil de trabajar. Y siempre puede attach una lista como entorno.

Editar: Si desea ver un ejemplo de proto en el trabajo en ggplot, echar un vistazo que la estructura de un objeto ggplot, que es esencialmente una lista compuesta parcialmente de ambientes:

> 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 

Observe cómo se construye utilizando proto y contiene muchos entornos como resultado. También puede trazar las relaciones en estos objetos usando graph.proto.

+0

Espero comprenderlos para poder utilizarlos potencialmente. Estoy familiarizado con las reglas de alcance en R y con la mayoría de las funciones que ha enumerado, pero exploraré los detalles con más profundidad. Gracias por la info. – ramhiser

+3

Totalmente de acuerdo, Shane! ¡Es importante comprender los entornos y el alcance en R si está creando una cantidad significativa de código! Pero eso no implica necesariamente que deba usar entornos como estructuras de datos. – Harlan

+2

@Harlan: estoy completamente de acuerdo. Tal vez debería ser más enérgico en ese frente. @John: No use entornos a menos que (1) los entienda y (2) tenga una buena razón para hacerlo. Una lista es generalmente una mejor opción. OMI, ¡es una buena práctica evitar los efectos secundarios a menos que no puedas! – Shane

5

Bueno, si no los entiende, y las personas que quizás algún día tengan que leer su código (incluido su yo futuro) no entienden los entornos, ¡entonces no deberían usarlos! Fueron diseñados para ser utilizados para encapsular espacios de nombre en paquetes y cosas por el estilo. El hecho de que puede utilizarlos para pasar por referencia y tablas hash no significa necesariamente que debe. Es un truco. En general, el uso de deep magic no es realmente recomendable, incluso si hace que su código sea un poco más rápido.

+1

Entonces, ¿cada vez que encuentro un truco nuevo, debería evitarlo porque no lo entiendo? A menudo realizo operaciones en matrices de covarianza grandes pasándolas de una función a otra. ¿El uso de entornos mejoraría el rendimiento en esta situación lo suficiente como para justificar su uso? – ramhiser

+0

No estoy del todo seguro de los detalles de la implementación, pero creo que si no modifica las matrices grandes dentro de las funciones, en realidad no se copian. En cuanto a su pregunta más amplia, le aconsejo que si necesita la velocidad, puede valer la pena aprender la magia, solo tenga en cuenta que es un abuso (leve) de la semántica de los lenguajes para hacerlo, y que puede lamentarlo luego. ¡O puede que no te arrepientas! – Harlan

+4

+1 Para tener en cuenta las preocupaciones de Harlan: sí, este es un uso peligroso porque presenta "efectos secundarios". Cada vez que permite que una función altere el mundo exterior, se está abriendo a un comportamiento inesperado. http://en.wikipedia.org/wiki/Side_effect_(computer_science) – Shane

Cuestiones relacionadas