I’ve read the documentation for parent.env() and it seems fairly straightforward – it returns the enclosing environment. However, if I use parent.env() to walk the chain of enclosing environments, I see something that I cannot explain. First, the code (taken from “R in a nutshell”)
library( PerformanceAnalytics )
x = environment(chart.RelativePerformance)
while (environmentName(x) != environmentName(emptyenv()))
{
print(environmentName(parent.env(x)))
x <- parent.env(x)
}
And the results:
[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"
How can we explain the “base” at the top and the “base” at the bottom? Also, how can we explain “package:PerformanceAnalytics” and “imports:PerformanceAnalytics”? Everything would seem consistent without the first two lines. That is, function chart.RelativePerformance is in the package:PerformanceAnalytics environment which is created by xts, which is created by zoo, … all the way up (or down) to base and the empty environment.
Also, the documentation is not super clear on this – is the “enclosing environment” the environment in which another environment is created and thus walking parent.env() shows a “creation” chain?
Edit
Shameless plug: I wrote a blog post that explains environments, parent.env(), enclosures, namespace/package, etc. with intuitive diagrams.
The first few items in your results give evidence of the rules R uses to search for variables used in functions in packages with namespaces. From the R-ext manual:
Elaborating just a bit, have a look at the first few lines of
chart.RelativePerformance:When a call to
chart.RelativePerformanceis being evaluated, each of those symbols — whether thecheckDataon line 1, or thencolon line 3 — needs to be found somewhere on the search path. Here are the first few enclosing environments checked:First off is
namespace:PerformanceAnalytics.checkDatais found there, butncolis not.Next stop (and the first location listed in your results) is
imports:PerformanceAnalytics. This is the list of functions specified as imports in the package’sNAMESPACEfile.ncolis not found here either.The
baseenvironment namespace (wherencolwill be found) is the last stop before proceeding to the normal search path. Almost any R function will use somebasefunctions, so this stop ensures that none of that functionality can be broken by objects in the global environment or in other packages. (R’s designers could have left it to package authors to explicitly import thebaseenvironment in theirNAMESPACEfiles, but adding this default pass throughbasedoes seem like the better design decision.)