Does a parent exist in an environment that does not have a search path?
I am reading the book Hadley Wickham Advanced R and am currently reading the chapter "Environment"
It says that every environment except empty has a parent. I need help figuring out something that clears this up to me - maybe I am just over the top or misunderstanding how variables work in R.
Let's say I define my own environment: myenv <- new.env()
Now if I do simple parent.env(myenv)
, I get a global env as expected.
But now what happens when I attach this environment, forcing it to follow the search path above the global env? attach(myenv)
Now if I look at the search path using search()
I can see what myenv
the parent is .GlobalEnv
. I can also test this using parent.env(globalenv())
that returns myenv
. And if I run it parent.env(parent.env(globalenv()))
, then we get tools:rstudio
what makes sense.
BUT if I try to look at the parent myenv
directly using parent.env(myenv)
. I am getting a global env. I expect ( tools:rstudio
) to get the result . I need to manually switch environment to environment: parent.env(as.environment("myenv"))
returns tools:rstudio
.
So which is correct? What is myenv parent environment?
I know I can change the parent of the environment with parent.env<-
, but if I just attach it like in the example above, I don't understand what counts as a true parent
source to share
The problem is that the binding myenv
creates a copy myenv
(and also changes its parent), so now we have two environments myenv
, and they can be different. You have already shown in the question that they have different parents. Try this in a new session to show that they are different:
myenv <- new.env()
myenv$x <- 1
# with the attach below we now have 2 myenv environments -
# the one above and the new one created in the attach below on the search path.
attach(myenv)
# this changes x in the original myenv but not the x in the copy on the search path
myenv$x <- 2
myenv$x
## 2
# the copy of myenv on the search path still has the original value of x
as.environment("myenv")$x
## 1
Read more on this blog .
source to share
The parent environment is the shell from which you defined the new environment. However, this is not the case for functions. If you define a function, the parent frame will be the environment from which it is called, not defined (see help(sys.parent)
).
The environmental documentation is quite informative.
new.env
returns a new (empty) environment with (default) wrapped around the parent frame.
parent.env
returns the environment of its argument's environment.
Therefore, it should come as no surprise that the parent environment is the global environment. If you were assigned myenv
in another application, this would be its parent.
Empty env is the end of the line
parent.env(baseenv())
# <environment: R_EmptyEnv>
parent.env(parent.env(baseenv()))
# Error in parent.env(parent.env(baseenv())) :
# the empty environment has no parent
And here's something else that's useful ...
If you follow the chain of shells found by calling multiple times
parent.env
from any environment, eventually one reaches an empty environmentemptyenv()
to which nothing can be assigned.
I guess it also depends on what is in the search path and whether you are attaching it to the search path.
myenv <- new.env()
attach(myenv)
sapply(search(), function(x) {
attr(parent.env(as.environment(x)), "name")
})
Which gives a list of environments and their parents in the search along my way.
$.GlobalEnv
[1] "myenv"
$myenv
[1] "package:stringi"
...
...
$`package:base`
NULL
[[12]]
<environment: R_EmptyEnv>
source to share