2011-12-26 12 views
10

He leído la documentación para parent.env() y parece bastante sencillo: devuelve el entorno adjunto. Sin embargo, si uso parent.env() para recorrer la cadena de entornos circundantes, veo algo que no puedo explicar. En primer lugar, el código (tomado de "R en una cáscara de nuez")parent.env (x) confusion

library(PerformanceAnalytics) 
x = environment(chart.RelativePerformance) 
while (environmentName(x) != environmentName(emptyenv())) 
{ 
    print(environmentName(parent.env(x))) 
    x <- parent.env(x) 
} 

Y los resultados:

[1] "imports:PerformanceAnalytics" 
[1] "base" 
[1] "R_GlobalEnv" 
[1] "package:PerformanceAnalytics" 
[1] "package:xts" 
[1] "package:zoo" 
[1] "tools:rstudio" 
[1] "package:stats" 
[1] "package:graphics" 
[1] "package:utils" 
[1] "package:datasets" 
[1] "package:grDevices" 
[1] "package:roxygen2" 
[1] "package:digest" 
[1] "package:methods" 
[1] "Autoloads" 
[1] "base" 
[1] "R_EmptyEnv" 

¿Cómo podemos explicar la "base" en la parte superior y la "base" en la parte ¿fondo? Además, ¿cómo podemos explicar "package: PerformanceAnalytics" e "imports: PerformanceAnalytics"? Todo parecería consistente sin las dos primeras líneas. Es decir, el gráfico de funciones. El rendimiento relativo está en el paquete: entorno PerformanceAnalytics creado por xts, que es creado por el zoológico, ... hasta arriba (o abajo) hasta la base y el entorno vacío.

Además, la documentación no es muy clara al respecto: ¿el "entorno circundante" es el entorno en el que se crea otro entorno y, por lo tanto, al caminar parent.env() muestra una cadena de "creación"?

Editar

Enchufe desvergonzado: Me escribió una blog post que explica ambientes, parent.env(), recintos, espacio de nombres/paquete, etc. con diagramas intuitivos.

+0

gracias a todos los que contribuyeron a esta pregunta. Fue difícil elegir una respuesta porque todas las publicaciones fueron excelentes – SFun28

Respuesta

3

Los primeros elementos en sus resultados evidencian las reglas que R usa para buscar variables usadas en funciones en paquetes con espacios de nombres. De R-ext manual:

El espacio de nombres controla la estrategia de búsqueda de las variables utilizadas por las funciones del paquete. Si no se encuentra localmente, R busca primero el espacio de nombres del paquete, luego las importaciones, luego el espacio de nombre base y luego la ruta de búsqueda normal.

Abundando un poco, echar un vistazo a las primeras líneas de chart.RelativePerformance:

head(body(chart.RelativePerformance), 5) 
# { 
#  Ra = checkData(Ra) 
#  Rb = checkData(Rb) 
#  columns.a = ncol(Ra) 
#  columns.b = ncol(Rb) 
# } 

Cuando se evalúa una llamada a chart.RelativePerformance, cada uno de esos símbolos --- si el checkData en línea 1, o ncol en la línea 3 --- debe encontrarse en algún lugar de la ruta de búsqueda. Estos son los primeros pocos entornos de cerramiento controladas:

  • En primer lugar es namespace:PerformanceAnalytics. checkData se encuentra allí, pero ncol no lo está.

  • La siguiente parada (y la primera ubicación que figura en sus resultados) es imports:PerformanceAnalytics. Esta es la lista de funciones especificadas como importaciones en el archivo NAMESPACE del paquete. ncol no se encuentra aquí tampoco.

  • El espacio de nombres del entorno base (donde se encuentra ncol) es la última parada antes de proceder a la ruta de búsqueda normal. Casi cualquier función R utilizará algunas funciones base, por lo que esta detención garantiza que ninguna de esas funciones pueda romperse por objetos en el entorno global o en otros paquetes.(Diseñadores de R podrían haber dejado a empaquetar autores importar de forma explícita el medio ambiente base en sus NAMESPACE archivos, pero la adición de este paso predeterminado a través base parece como la mejor decisión de diseño.)

+0

Josh, pero estoy llamando a parent.env(), que es el entorno que lo rodea. ¿Estoy entendiendo mal qué se supone que parent.env() debe hacer? De acuerdo con la cadena de arriba, el entorno gobal es una base "principal" o "encierra" y abajo de la base de la línea encierra "Autoloads", por lo que en efecto la base incluye la base. Entonces, ¿estamos diciendo que parent.env() realmente no es el entorno circundante hasta que llegue al entorno global? – SFun28

+0

@ SFun28 Mi comprensión (imperfecta) es que "padre-hijo" puede ser una metáfora engañosa de env. Un env incluido es más un puntero de donde R se ve a continuación que una relación de contención estricta. Entonces, probablemente puedas construir todo tipo de cadenas de env no intuitivas que se repiten sobre sí mismas. – joran

+0

Oh, creo que veo tu preocupación. Como G. Grothendieck & kohske enfatizó, la primera 'base' buscada se llama' namespace: base', para hacer posible este mecanismo de búsqueda. Su contenido es idéntico a 'paquete: base', como se muestra al intentar' idéntico (ls (baseenv()), ls (.BaseNamespaceEnv)) ' –

3

El segundo base es .BaseNamespaceEnv, mientras que penúltimo base es baseenv(). Estos no son diferentes (probablemente por sus padres). El padre de .BaseNamespaceEnv es .GlobalEnv, mientras que el de baseenv() es emptyenv().

En un paquete, como dice @Josh, R busca el espacio de nombres del paquete, luego las importaciones y luego la base (es decir, BaseNamespaceEnv).

usted puede encontrar esto, por ejemplo .:

> library(zoo) 

> packageDescription("zoo") 
Package: zoo 

# ... snip ... 

Imports: stats, utils, graphics, grDevices, lattice (>= 0.18-1) 

# ... snip ... 

> x <- environment(zoo) 

> x 
<environment: namespace:zoo> 

> ls(x) # objects in zoo 
    [1] "-.yearmon"    "-.yearqtr"    "[.yearmon"    
    [4] "[.yearqtr"    "[.zoo"     "[<-.zoo"     
# ... snip ... 

> y <- parent.env(x) 
> y # namespace of imported packages 
<environment: 0x116e37468> 
attr(,"name") 
[1] "imports:zoo" 

> ls(y) # objects in the imported packages 

    [1] "?"          "abline"        
    [3] "acf"         "acf2AR"        
# ... snip ... 
+0

kohske - ¡ah! No me di cuenta de que estos son dos ambientes diferentes. Entonces, ¿realmente cada entorno impreso es un entorno único? Estoy empezando a ver una confusión entre los entornos de "espacio de nombres", "importaciones" y "paquete". No se muestra el entorno de la primera x que es "namespace: PerformanceAnalytics".¿Podría aclarar las diferencias entre estos entornos, cuándo se cargan y cómo se relacionan entre sí? – SFun28

+0

gracias por la elaboración de su respuesta, ¡ayudó mucho! – SFun28

5

1) con respecto a cómo podría ser base allí dos veces (dado que los entornos forman un árbol), la culpa de la función environmentName. En realidad, la primera aparición es .BaseNamespaceEnv y la última aparición es baseenv().

> identical(baseenv(), .BaseNamespaceEnv) 
[1] FALSE 

2) En cuanto a la imports:PerformanceAnalytics que es un entorno especial que R configura para mantener las importaciones mencionadas en el archivo NAMESPACE o descripción del paquete de modo que los objetos en que se encuentran antes que nada.

Intenta ejecutar esto para mayor claridad. Los str(p) y siguiendo if declaraciones dará una mejor idea de lo que es p:

library(PerformanceAnalytics) 
x <- environment(chart.RelativePerformance) 
str(x) 
while (environmentName(x) != environmentName(emptyenv())) { 
    p <- parent.env(x) 
    cat("------------------------------\n") 
    str(p) 
    if (identical(p, .BaseNamespaceEnv)) cat("Same as .BaseNamespaceEnv\n") 
    if (identical(p, baseenv())) cat("Same as baseenv()\n") 
    x <- p 
} 
+0

¡Eso es fantástico! La relación parent.env es mucho más fácil de ver con este código. Tengo curiosidad, ¿cuál es la ventaja de importar en un paquete? He creado mi propio paquete pero no uso importaciones. ¿Es simplemente para encontrar símbolos más rápidamente o dar un símbolo de mayor precedencia que el mismo símbolo en la base? – SFun28

+0

Al usar 'import', puede hacer que los objetos en los paquetes de importación sean invisibles para los usuarios. Si su paquete A importa B, puede usar objetos de B de su paquete. Pero los usuarios no pueden usar los objetos de B incluso después de cargar A. – kohske

+0

por cierto, esta es una gran función de utilidad/ayuda (es decir, envolviendo su código en una función llamada SearchPath (x)). Parece que R proporciona una función de búsqueda() y searchpaths(), pero no nos permite especificar un punto de partida que no sea globalenv – SFun28