--- title: "Module environments" author: Konrad Rudolph date: "`r Sys.Date()`" output: rmarkdown::html_vignette: toc: true md_document: variant: gfm vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{Module environments} %\VignetteEncoding{UTF-8} ---
c.r
```{r eval = FALSE}
#' @export
f = function () 'c$f'
```
Module `c` defines and exports one name, the function `f`.
### b.r
```{r eval = FALSE}
#' @export
f = function () 'b$f'
g = function () 'b$g'
```
Module `b` defines and exports the function `f`, and in addition defines
the function `g`.
### a.r
```{r eval = FALSE}
#' @export
box::use(./b[g = f, ...])
box::use(./c[...])
#' @export
box::use(./c)
#' @export
f = function () 'a$f'
f_of_c1 = c$f
f_of_c2 = get('f', parent.env(environment()))
stopifnot(identical(f_of_c1, f_of_c2))
```
Module `a` imports and re-exports all names from `b` (changing the name
of `b$f` to `g`); it also imports, but does not re-export, all names
from `c` (and, additionally, defines an alias for the module, which it
exports).
It further defines and exports the function `f` and defines, but does
not export, the functions `f_of_c1` and `f_of_c2` (which are defined
such that they are identical to each other — hopefully it will become
clear why later).
Finally, let’s use the modules by executing the following code:
```{r eval = FALSE}
box::use(a = ./a[f, g])
```
Now the name `a` is defined in `.GlobalEnv` and refers to the module
environment of module `a`. The exported names `f` and `g` of `a` are
also available in `.GlobalEnv` (but not defined *inside* `.GlobalEnv`).
The loaded modules can be represented by the following schematic, with
each box corresponding to an environment:

Let’s go over the different types of environment associated with each
module, and how they are connected.
## Environments
### Module namespace
Modules are loaded into their own dedicated environment, the *module
namespace*. Every name that is defined by a module is defined inside it.
It is thus also the enclosing environment of the module’s functions.
Lastly, the module namespace also stores meta-information about the
module in a hidden member named `.__module__.`.
This corresponds to the package namespace.
### Module imports environment
The parent environment of the module namespace is the imports
environment, which contains all the names that a module imports via
attachment declarations in `box::use` expressions.
The parent environment of the imports environment is the R `base`
namespace environment. The module imports environment thus corresponds
to the package imports environment.
### Module export environment
The module export environment, also called just “module environment” in
the code base, contains all names that are marked as exported by a
module. If users create a module alias in their `box::use` call, the
alias will be a reference to this environment.
Similarly, attached names are selected as a subset from the module
export environment (then copied into the imports environment).
There is no direct equivalent to this environment in R packages, because
R packages do not distinguish between exported names and names imported
by the code that loaded the package. By contrast, ‘box’ needs to
distinguish the set of exports from the set of names that are imported
(= “attached”) by client code.
### Importing into other environments
Module import environments store imports from one or more module into
another. However, modules can also be imported from inside the global
environment, or from inside functions, which have their own local
execution environment (the stack frame). When this happens, a new
imports environment is created on the fly, and attached to the importing
environment’s `parent.env` chain. Calling `box::use` with a non-empty
attach list in `.GlobalEnv` is therefore similar to calling `library`.
In particular, inside `.GlobalEnv` the call `box::use(pkg[...])` in
pretty much equivalent to calling `library(pkg)`, and is discouraged for
the same reason that `library(pkg)` is discouraged.