Code
= function (x) {
sum = 0
S
for (i in x) {
= S + i
S
}
S }
When working with modules during development, you’ll frequently modify the source code, and need those changes to reflect in your current R session. Understanding how {box} handles module reloading to increase development workflow efficiency.
This section primarily applies to modules created from scripts and folders, not R packages loaded from CRAN or other repositories.
By default, {box} caches modules after the first import. This improves performance but means changes to your module files won’t automatically appear in your current session.
In this example, imagine you have {./utils/helpers}:
::use(./utils/helpers)
box
$my_function() # Works as expected helpers
Then eventually, you made some modification to helpers.r
and run the import again in the same session:
::use(./utils/helpers)
box
$my_function() # Still uses old version! helpers
Here’s the problem: second import that uses box::use()
, uses cached version, and the changes you made in {./utils/helpers} will NOT be reflected.
There are some reasons why caching happens:
This behavior mirrors how R packages work - once loaded with library()
, they remain in memory until the session restarts.
box::reload()
After importing {./utils/helpers} as ./helpers module, reload ./helpers with box::use()
.
To see changes made to a module without restarting R, see what I mean:
You already did an initial import of {./utils/helpers}, saved as ./helpers module:
::use(./utils/helpers) box
Make some changes in {./utils/helpers}
Reload ./helpers to see
::reload(helpers) box
Now the updated version is loaded
$my_function() helpers
I made a practical examples that you can replicate in your current sessions somewhere. First, create ./utils folder then create an R script named helpers.r. Once {./utils/helpers} is loaded via box::use(./utils/helpers)
, {.helpers} module is made.
3 scenarios that I know of when you made some changes and then reload the {.helpers} module
This is what {./utils/helpers} contains of:
= function (x) {
sum = 0
S
for (i in x) {
= S + i
S
}
S }
Then, in your R session:
::use(./utils/helpers)
box= 1 : 10
x $sum(x) helpers
Then, change your mind because it will not work once the vector x
contains missing values NA
:
::use(
box
stats[na.omit]
)
= function (x, na.rm = FALSE) {
sum if (na.rm) {
= na.omit(x)
x
}
= 0
S for (i in x) {
= S + i
S
}
S }
Reload {.helpers} to utilize the changes made:
::reload(helpers)
box= 1 : 10
x 4] = NA
x[
$sum(x)
helpers#> 51
Originally, {./utils/helpers} contains only 1 function. How about we made changes in {.helpers} module by adding new functions?
For example, you want a new function {./utils/helpers} that calculates the mean:
::use(
box
stats[na.omit]
)
= function (x, na.rm = FALSE) {
sum if (na.rm) {
= na.omit(x)
x
}
= 0
S for (i in x) {
= S + i
S
}
S
}
= function (x, na.rm = FALSE) {
mean if (na.rm) {
= na.omit(x)
x
}
= sum(x)
S = length(x)
n
= S / n
out
out }
Since it caches the recent {./utils/helpers} import, mean()
from {.helpers} won’t be available, thus a simple error.
= 1 : 10
x 4] = NA
x[
$mean(x, na.rm = TRUE)
helpers#> Error in helpers$mean : name 'mean' not found in 'helpers'
Once again, reload {.helpers}:
::reload(helpers) box
And helpers$mean()
will be available:
= 1 : 10
x 4] = NA
x[
$mean(x, na.rm = TRUE)
helpers#> [1] 5.7
What if we only export mean()
from {./utils/helpers}? Fortunately, {box} borrows Roxygen2 API, and this includes #' @export
.
::use(
box
stats[na.omit]
)
= function (x, na.rm = FALSE) {
sum if (na.rm) {
= na.omit(x)
x
}
= 0
S for (i in x) {
= S + i
S
}
S
}
#' @export
= function (x, na.rm = FALSE) {
mean if (na.rm) {
= na.omit(x)
x
}
= sum(x)
S = length(x)
n
= S / n
out
out }
Reload {.helpers} with box::reload()
and sum()
will not be available to {.helpers}:
::reload(helpers)
box
= 1 : 10
x 4] = NA
x[
$mean(x, na.rm = TRUE)
helpers#> [1] 5.7
$sum(x, na.rm = TRUE)
helpers#> Error in helpers$sum : name 'sum' not found in 'helpers'
The function box::reload()
ONLY reloads the module, not the functions or objects under the namespace of the module. Trying to reload function will throw an error saying Error in box::reload(custom_mean) : "reload” expects a module object, got “fun”, which is of type “function” instead
::use(
box/utils/helpers[custom_mean = mean]
.
)
::reload(custom_mean)
box#> Error in box::reload(custom_mean) :
#> “reload” expects a module object, got “custom_mean”, which is of type “function” instead
The best solution is to restart the session, and the environment/s created by box::use()
will absolve, and once again, the current environment is now cleansed.
To be frank, an R session is simply just a running instance of the R interpreter — the environment where R executes code, stores objects, and manages the workspace. When you start R (via terminal, RStudio, VS Code, or any other interface), you are launching a fresh R session.
The question is, when to use box::reload()
versus restarting your R session?
Use box::reload()
when:
Restart R session when:
box::use()
, only accepting modules.box::use()
.In RStudio, restart R with Ctrl/Cmd + Shift + F10. This clears everything and gives you a fresh start without closing RStudio.