2012-09-19 26 views
7

Estoy tratando de usar get en una serie de llamadas a funciones, pero la búsqueda de los nombres de los objetos parece omitir entornos. Por ejemplo:R entornos y pilas de llamadas de función

foo <- 1 # variable in .GlobalEnv 

getter <- function(x) {get(x)} 
getter("foo") # returns 1, which is expected 

f1 <- function() { 
    foo <- 2 # local variable in the function scope 
    getter("foo") 
} 

f1() # still returns 1, would've expected to return 2 

Por qué es que llamar f1 devuelve el foo en el entorno global y no el foo en el entorno de la función de llamada?

¿Cómo se ve get en el entorno de la función de llamada? El ajuste pos = sys.parent() no parece funcionar.

Respuesta

6

Si define getter a mirarse en el marco padre, funciona:

getter <- function(x) get(x, envir=parent.frame()) 

continuación:

getter("foo") 
[1] 1 

f1() 
[1] 2 
+1

¡Eso lo hizo, gracias! ¿Por qué funciona parent.frame() pero no sys.parent()? ¿Existe un documento que discuta cómo funcionan todas estas diferentes funciones y las diferencias entre referirse a los entornos por número o por nombre? – hgcrpd

+2

@hgcrpd 'sys.parent' devuelve un número entero, no el marco/entorno. 'parent.frame' usa la información' sys.parent' con 'sys.frame' para obtener el marco (no solo su valor entero). –

13

Usted está siendo disparado por las sutiles diferencias entre los marcos y entornos (que es aún más sutil ya que los marcos son entornos, o tal vez los entornos son marcos) y la diferencia entre lexical and dynamic scoping. Hay algunos detalles en la página de ayuda para parent.frame y otros lugares distribuidos en diversos documentos.

Para tratar de simplificar:

Su función getter tiene su propio environment donde se almacenan las variables locales a esa función (x en este caso). Como R tiene un alcance léxico, significa que el entorno de las funciones tiene un entorno primario definido por donde se define la función, el entorno global en este caso (si estuviera definido dentro de otra función, entonces el entorno primario sería el entorno para ese función).

Cuando se llama a f1 y llama getter continuación captador trata de encontrar la variable foo, primero busca en su propio entorno, no lo encuentra allí, entonces se ve en su entorno matriz que es el env mundial y se encuentra foo con el valor de 1.

Su pensamiento va en la misma línea del alcance dinámico, que los cuadros se aproximan. Cuando se llama al f1 obtiene su propio entorno (dentro del cual foo se le asignará el valor 2), entonces llama a la función getter. El entorno de foo no es el padre de env getter 's (ámbito léxico), pero el entorno de f1 es el marco principal de getter desde getter fue llamado desde f1, por lo que buscar en el entorno de f1 tiene que decirle a la get función para buscar en el marco principal en lugar del entorno principal.

El resumen de esto es que el entorno primario es el entorno donde se definió una función (ámbito léxico), el marco principal es el marco/entorno desde el que se llamó a la función (ámbito dinámico simulado).

+2

+1 Muy buena explicación, gracias.Esto merece ser la respuesta aceptada. Si combina mi solución de código, eliminaré mi respuesta, para que la suya pueda ser aceptada. – Andrie

+0

@Andrie Creo que ambas respuestas son buenas, el tuyo resolvió el problema inmediato y el mío dio el trasfondo. No tengo ningún problema con los dos restantes y cuál es el aceptado debe ser la decisión del cartel original. Aprecio tu voto positivo. –

+0

gracias a ambos, esto fue muy útil. – hgcrpd

Cuestiones relacionadas