2011-10-26 19 views
14

Quiero entender mejor cómo están relacionados environments, closures y frames. Entiendo que los cierres de funciones contienen un entorno, los entornos contienen un marco y un recinto, y los marcos contienen variables, pero estoy un poco confuso sobre cómo interactúan entre sí.¿Cómo se relacionan los entornos, (en) cierres y marcos?

Quizás un ejemplo de lo que está sucediendo durante una llamada a función ayudaría? ¿O tal vez un diagrama?

+0

@DirkEddelbuettel: No es modestia; los ponis son desordenados No he leído eso. Tomaré una copia y responderé mi propia pregunta. –

+1

¿Mi respuesta es similar a la que estaba buscando o debería aclarar alguna parte? – Tommy

Respuesta

10

ACTUALIZACIÓN R-lang define un environment como que tiene un bastidor. Tiendo a pensar en marcos como marcos de pila, no como mapeando de nombre a valor, pero luego está, por supuesto, el data.frame que asigna nombres de columna a vectores (y luego algunos ...). Creo que la mayor parte de la confusión proviene del hecho de que el lenguaje S original (y aún S-Plus) no tenía objetos de entorno, por lo que todos los "marcos" eran esencialmente lo que son los objetos de entorno ahora, excepto que solo podían existir como parte de la pila de llamadas.

Por ejemplo, en S-Plus el documento para sys.nframe dice "sys.nframe devuelve el índice numérico del fotograma actual en la lista de todos los fotogramas". ... me suena mucho a montones de montones ... Puede leer más sobre montones de montículos aquí: http://en.wikipedia.org/wiki/Call_stack#Structure

Expandí algunas de las explicaciones a continuación y utilizo el término "marco de pila" consistentemente (espero)

FIN DE ACTUALIZACIÓN

Me explico como esto:

  1. Un entorno es un objeto que asigna nombres de variables a los valores. Cada mapeo se llama un enlace. El valor puede ser un valor real o una promesa. Un entorno tiene un entorno principal (a excepción del entorno vacío). Cuando busca un símbolo en un entorno y no se encuentra, también se buscan los entornos principales.

  2. Una promesa es una expresión no evaluada y un entorno en el que evaluar la expresión. Cuando se evalúa la promesa, se reemplaza con el valor generado.

  3. Un cierre es una función y el medio ambiente que la función se define en una función como lm tendría el entorno de las estadísticas de espacio de nombres y una función definida por el usuario tendría el entorno global -. Sino una función f definido dentro de otra función g tendría el entorno local para g como su entorno.

  4. Un marco de pila (o registro de activación) es lo que representa las entradas en la pila de llamadas. Cada marco de pila tiene el entorno local en el que se ejecuta la función y la expresión de la llamada de función (de modo que sys.call funciona).

  5. Cuando se ejecuta una llamada de función, se crea un entorno local con su entorno principal en el entorno de cierre, los argumentos se comparan con los argumentos formales de la función y esos enlaces se agregan al entorno local (como promete). A los argumentos formales no coincidentes se les asignan los valores predeterminados (promesas) de la función (si corresponde) y se marcan como faltantes. A continuación, se crea un marco de pila con este entorno local y la expresión de llamada. El marco de pila se empuja en la pila de llamadas y luego el cuerpo de la función se evalúa en este entorno local.

... así que todos los símbolos en el cuerpo será buscado en el entorno local (argumentos formales y variables locales), y si no se encuentra en el entorno de los padres (que es el ambiente de cierre) y la matriz de entorno principal y así sucesivamente hasta que se encuentre.

Tenga en cuenta que el entorno del marco de la pila padre es NO buscado en este caso. El parent.frame, sys.frame funciones obtiene los entornos en la pila de llamadas - es decir, el entorno de la persona que llama y el medio ambiente de la persona que llama de la persona que llama, etc ...

# Here match.fun needs to look in the caller's caller's environment to find what "x" is... 
f <- function(FUN) match.fun(FUN)(1:10) 
g <- function() { x=sin; y="x"; f(y) } 
g() # same as sin(1:10) 

# Here we see that the stack frames must also contain the actual call expression 
f <- function(...) sys.call() 
g <- function(...) f(..., x=42) 
g(a=2) # f(..., x = 42) 
+0

Gracias por su respuesta. R-lang dice que un entorno _consiste_ de un marco (que consiste en enlaces símbolo/valor) y un recinto (¿el entorno padre?), Que es ligeramente diferente de # 1. # 4 es confuso debido a las diferencias entre R-lang y su definición en # 1, y cómo R-lang describe la pila de llamadas con palabras como "marco de evaluación", "contextos" y "entornos". No sé si esas son 3 cosas diferentes o si el autor de ese párrafo estaba siendo poco claro con la terminología. Tu último párrafo no está claro. ¡Gracias de nuevo! –

+0

@JoshuaUlrich - Actualicé mi respuesta. Espero que aclare las cosas (claro como el barro !?) – Tommy

+0

Esta respuesta tiene mucho sentido para mí. ¡Gracias! – Iterator

5

¿Responde this extended description by John Fox a sus preguntas?

Tiene buenos diagramas, pero no ponies.

También hay una descripción en el Fox & Weisberg book, "An R Companion to Applied Regression" (2011), a partir de p. 417, o la sección 8.9.1. Creo que el PDF anterior, aunque es más antiguo, es probablemente igual de informativo, si no más (debido a los diagramas). F & W es un buen libro, que he enchufado a couple de veces antes, para other useful stuff. FWIW, no encontré ninguna información útil en el libro "R in a Nutshell". Aunque aún no tengo ninguno de los libros de Chambers.

Cuestiones relacionadas