2012-01-25 17 views
6

¿Es posible utilizar env() como sustituto de los espacios de nombres, y cómo comprobar si ya existe un entorno antes de agregarle funciones?cómo agregar funciones en un entorno existente

esto está relacionado con esta cuestión, y la sugerencia de Brendan How to organize large R programs? entiendo el punto de Dirk en esa pregunta, sin embargo, para el desarrollo a veces es poco práctico para poner funciones en paquetes.

EDITAR: La idea es imitar los espacios de nombres en los archivos y, por lo tanto, poder cargar diferentes archivos de forma independiente. Si un archivo se ha cargado previamente, entonces no es necesario crear el entorno, solo agregarlo a.

Gracias por las ideas

EDIT: De modo que probablemente este código de abajo sería el equivalente de espacios de nombres en otros idiomas: -

# how to use environment as namespaces 

# file 1 

# equivalent of 'namespace e' if (!(exists("e") && is.environment(e))) { e <- new.env(parent=baseenv()) } 

e$f1 <- function(x) {1} 


# file 2 
# equivalent of 'namespace e' if (!(exists("e") && is.environment(e))) { e <- new.env(parent=baseenv()) } 

e$f2 <- function(x) {2} 
+3

Organizo * mucho * de mi código en paquetes, pero utilizo el paquete 'devtools' de Hadley para cargarlo en un entorno. Esto esencialmente logra lo que describes, pero también tengo la ventaja adicional de que puedo construir y volver a usar el paquete si quiero. (En otras palabras, no necesito reconstruir continuamente el paquete mientras desarrollo). – Andrie

Respuesta

2

Usted puede comprobar que existen ambientes de la misma manera que lo haría con cualquier otra variable.

e <- new.env() 
exists("e") && is.environment(e) 
5

Sí, usted puede en su mayor parte. Cada función tiene un entorno y es allí donde busca otras funciones y variables globales. Al usar su propio entorno, usted tiene control total sobre eso.

Normalmente, las funciones también tienen asignado a un entorno (asignándolas a un nombre), y normalmente esos dos entornos son los mismos, pero no siempre. En un paquete, el entorno del espacio de nombres se usa para ambos, pero luego el entorno del paquete (diferente) en la ruta de búsqueda también tiene las mismas funciones (exportadas) definidas. Entonces, los ambientes son diferentes.

# this will ensure only stats and packages later on the search list are searched for 
# functions from your code (similar to import in a package) 
e <- new.env(parent=as.environment("package:stats")) 

# simple alternative if you want access to everything 
# e <- new.env(parent=globalenv()) 

# Make all functions in "myfile.R" have e as environment 
source("myfile.R", local=e) 

# Or change an existing function to have a new environment: 
e$myfunc <- function(x) sin(x) 
environment(e$myfunc) <- e 

# Alternative one-liner: 
e$myfunc <- local(function(x) sin(x), e) 

# Attach it if you want to be able to call them as usual. 
# Note that this creates a new environment "myenv". 
attach(e, name="myenv") 

# remove all temp objects 
rm(list=ls()) 

# and try your new function: 
myfunc(1:3) 

# Detach when it's time to clean up or reattach an updated version... 
detach("myfile") 

En el ejemplo anterior, e corresponde a un espacio de nombres y el adjunto "myenv" corresponde a un entorno de paquete (como "paquete: estadísticas" en la ruta de búsqueda).

4

Los espacios de nombres son entornos, por lo que puede utilizar exactamente el mismo mecanismo. Como R usa el alcance léxico, el padre del entorno define lo que verá la función (es decir, cómo se vinculan las variables libres). Y exactamente como el espacio de nombre, puede adjuntar entornos y buscarlos.

Así que para crear un nuevo "espacio de nombres manual" se puede usar algo como

e <- new.env(parent=baseenv()) 
# use local(), sys.source(), source() or e$foo <- assignment to populate it, e.g. 
local({ 
    f <- function() { ... } 
    #... 
}, e) 
attach(e, name = "mySuperNamespace") 

Ahora se carga y se adjunta al igual que un espacio de nombres - para que pueda utilizar f al igual que lo fue en un espacio de nombres. Los espacios de nombres utilizan un entorno principal más para resolver las importaciones; también puede hacerlo si le interesa. Si necesita verificar su entorno fresco, simplemente verifique la ruta de búsqueda, por ejemplo, "mySuperNamespace" %in% search(). Si necesita el entorno real, use as.environment("mySuperNamespace")

Cuestiones relacionadas