| Title: | Manage R Environments Better |
|---|---|
| Description: | Provides a small set of functions for managing R environments, with defaults designed to encourage usage patterns that scale well to larger code bases. It provides: import_from(), a flexible way to assign bindings that defaults to the current environment; include(), a vectorized alternative to base::source() that also default to the current environment; and attach_eval() and attach_source(), a way to evaluate expressions in attached environments. Together, these (and other) functions pair to provide a robust alternative to base::library() and base::source(). |
| Authors: | Tomasz Kalinowski [aut, cre] |
| Maintainer: | Tomasz Kalinowski <[email protected]> |
| License: | GPL-3 |
| Version: | 0.3.0 |
| Built: | 2026-05-11 07:23:41 UTC |
| Source: | https://github.com/t-kalinowski/envir |
Evaluate R expressions in an attached environment.
attach_eval( unquoted_expr, name = "local:utils", pos = 2L, warn.conflicts = TRUE, ..., expr = substitute(unquoted_expr), mask.ok = NULL )attach_eval( unquoted_expr, name = "local:utils", pos = 2L, warn.conflicts = TRUE, ..., expr = substitute(unquoted_expr), mask.ok = NULL )
unquoted_expr |
The expression to be evaluated, This is automatically quoted. |
name |
The environment name. If an environment of that name already exists, it is reused, otherwise, a new environment is attached. |
pos |
The position where to attach the environment, if creating a new
one. If an environment of |
warn.conflicts |
logical. If TRUE (the default), print warnings about objects in the attached environment that that are masking or masked by other objects of the same name. |
... |
Ignored. |
expr |
An R language object. This is an escape hatch from the automatic
quoting of |
mask.ok |
character vector of names of objects that can mask objects on
the search path without signaling a warning if |
The result after evaluating expr, invisibly.
attach_eval({ my_helper_funct <- function(x, y) x + y }) search() # environment "local:utils" is now attached my_helper_funct(1, 1) # the local utility is now available detach(local:utils) # cleanupattach_eval({ my_helper_funct <- function(x, y) x + y }) search() # environment "local:utils" is now attached my_helper_funct(1, 1) # the local utility is now available detach(local:utils) # cleanup
Source R files into an attached environment
attach_source( ..., name = as_tidy_env_name(c(...), prefix = "source:"), recursive = FALSE, pos = 2L, chdir = FALSE, warn.conflicts = TRUE, mask.ok = NULL, parent = .GlobalEnv )attach_source( ..., name = as_tidy_env_name(c(...), prefix = "source:"), recursive = FALSE, pos = 2L, chdir = FALSE, warn.conflicts = TRUE, mask.ok = NULL, parent = .GlobalEnv )
... |
filepaths to R files, or paths to directories containing R files. |
name |
A string, the name for the attached environment. By default, the
name is constructed from paths supplied to |
recursive |
If directories are passed to |
pos |
The position where to attach the environment, if creating a new
one. If an environment of |
chdir |
logical. if TRUE, the R working directory is temporarily changed to the directory containing the file(s) being sourced. |
warn.conflicts |
logical. If TRUE (the default), print warnings about
objects in the attached environment that that are masking or masked by
other objects of the same name. If the environment specified by |
mask.ok |
character vector of names of objects that can mask objects on
the search path without signaling a warning if |
parent |
R environment. If an environment specified by |
The attached environment, invisibly.
import_from, set_library_default_pos
This is inspired by the python idiom from module import object as new_name.
import_from( x, ..., .into = parent.frame(), .parent = .GlobalEnv, .overwrite = interactive(), .chdir = FALSE, .recursive = FALSE, .pos = 2L )import_from( x, ..., .into = parent.frame(), .parent = .GlobalEnv, .overwrite = interactive(), .chdir = FALSE, .recursive = FALSE, .pos = 2L )
x |
a bare symbol name of a package, a character vector of filepaths, an
environment (which could be a python module), or any object with |
... |
objects to import from x into |
.into |
An R environment, or something coercible to one by
|
.parent, .chdir, .recursive
|
Only applicable if |
.overwrite |
One of |
.pos |
Only applicable if |
The R environment or object that x resolved to, invisibly.
If x is a package name, then no check is performed to ensure the
object being imported is an exported function. As such, import_from() can
be used to access package internal objects, though doing so is usually bad
practice.
show_whats_imported <- function(...) { import_from(...) setdiff(names(environment()), "...") } ## Importing from an R package # import one object show_whats_imported(envir, include) # rename an object on import show_whats_imported(envir, sys_source = include) # import all NAMESPACE exports show_whats_imported(envir, "*") show_whats_imported(envir) # missing `...` is interpreted as "*" # import all NAMESPACE exports, except for `include` show_whats_imported(envir, "*", -include) # import all NAMESPACE exports, except rename `include` to `sys_source` show_whats_imported(envir, "*", sys_source = include) # exclude more than one show_whats_imported(envir, "*", -include, -attach_eval) show_whats_imported(envir, "*", -c(include, attach_eval)) # import all NAMESPACE exports, also one internal function names `find_r_files` show_whats_imported(envir, "*", find_r_files) # import ALL package functions, including all internal functions show_whats_imported(envir, "**") # import ALL objects in the package NAMESPACE, including R's NAMESPACE machinery show_whats_imported(envir, "***") ## Importing from R files # setup dir.create(tmpdir <- tempfile()) owd <- setwd(tmpdir) writeLines(c("useful_function <- function() 'I am useful'", ".less_useful_fn <- function() 'less useful'"), "my_helpers.R") # import one function by name show_whats_imported("my_helpers.R", useful_function) # import all objects whose names don't start with a "." or "_" show_whats_imported("my_helpers.R", "*") # import all objects show_whats_imported("my_helpers.R", "**") # if the filepath to your scripts is stored in a variable, supply it in a call x <- "my_helpers.R" try(show_whats_imported(x)) # errors out, because no package 'x' # to force the value to be used, just supply it as a call rather than a bare symbol. # the simplest call can be just wrapping in () or {} show_whats_imported({x}) show_whats_imported((x)) show_whats_imported(c(x)) show_whats_imported({{x}}) # tidyverse style unquoting ## Importing R objects # if you have an actual R object that you want to import from, you will # have to supply it in a call x <- list(obj1 = "one", obj2 = "two") show_whats_imported({x}) ## Not run: # don't run this so we don't take a reticulate dependency import_from(reticulate, py_module = import) # rename object on import # import one object show_whats_imported(py_module("numpy"), random) # to prevent automatic conversion show_whats_imported(py_module("numpy", convert = FALSE), random) # import all objects that don't begin with a `_` # by default, other modules found in the module are also not imported show_whats_imported(py_module("glob"), "*") # to import EVERYTHING pass "**" # now includes modules that your modules imported, like `os` show_whats_imported(py_module("glob"), "**") rm(py_module) # clean up ## End(Not run) # cleanup setwd(owd) unlink(tmpdir, recursive = TRUE) rm(show_whats_imported, tmpdir, owd)show_whats_imported <- function(...) { import_from(...) setdiff(names(environment()), "...") } ## Importing from an R package # import one object show_whats_imported(envir, include) # rename an object on import show_whats_imported(envir, sys_source = include) # import all NAMESPACE exports show_whats_imported(envir, "*") show_whats_imported(envir) # missing `...` is interpreted as "*" # import all NAMESPACE exports, except for `include` show_whats_imported(envir, "*", -include) # import all NAMESPACE exports, except rename `include` to `sys_source` show_whats_imported(envir, "*", sys_source = include) # exclude more than one show_whats_imported(envir, "*", -include, -attach_eval) show_whats_imported(envir, "*", -c(include, attach_eval)) # import all NAMESPACE exports, also one internal function names `find_r_files` show_whats_imported(envir, "*", find_r_files) # import ALL package functions, including all internal functions show_whats_imported(envir, "**") # import ALL objects in the package NAMESPACE, including R's NAMESPACE machinery show_whats_imported(envir, "***") ## Importing from R files # setup dir.create(tmpdir <- tempfile()) owd <- setwd(tmpdir) writeLines(c("useful_function <- function() 'I am useful'", ".less_useful_fn <- function() 'less useful'"), "my_helpers.R") # import one function by name show_whats_imported("my_helpers.R", useful_function) # import all objects whose names don't start with a "." or "_" show_whats_imported("my_helpers.R", "*") # import all objects show_whats_imported("my_helpers.R", "**") # if the filepath to your scripts is stored in a variable, supply it in a call x <- "my_helpers.R" try(show_whats_imported(x)) # errors out, because no package 'x' # to force the value to be used, just supply it as a call rather than a bare symbol. # the simplest call can be just wrapping in () or {} show_whats_imported({x}) show_whats_imported((x)) show_whats_imported(c(x)) show_whats_imported({{x}}) # tidyverse style unquoting ## Importing R objects # if you have an actual R object that you want to import from, you will # have to supply it in a call x <- list(obj1 = "one", obj2 = "two") show_whats_imported({x}) ## Not run: # don't run this so we don't take a reticulate dependency import_from(reticulate, py_module = import) # rename object on import # import one object show_whats_imported(py_module("numpy"), random) # to prevent automatic conversion show_whats_imported(py_module("numpy", convert = FALSE), random) # import all objects that don't begin with a `_` # by default, other modules found in the module are also not imported show_whats_imported(py_module("glob"), "*") # to import EVERYTHING pass "**" # now includes modules that your modules imported, like `os` show_whats_imported(py_module("glob"), "**") rm(py_module) # clean up ## End(Not run) # cleanup setwd(owd) unlink(tmpdir, recursive = TRUE) rm(show_whats_imported, tmpdir, owd)
Source R files
include( files_andor_dirs, envir = parent.frame(), chdir = FALSE, recursive = FALSE )include( files_andor_dirs, envir = parent.frame(), chdir = FALSE, recursive = FALSE )
files_andor_dirs |
A character vector of filepaths to R files, or
directories containing R files. Directories are searched for files that end
with extension ".R" or ".r", ignoring those that start with a period ( |
envir |
An R environment. By default, the current R evaluation environment. |
chdir |
logical; if |
recursive |
whether to search directories recursively for R files. |
This is a vectorized wrapper around base::sys.source with some
differences. Notably:
envir defaults to the current frame
envir is returned (invisibly)
keep.source and keep.parse.data default to
getOption("keep.source") and getOption("keep.parse.data") respectively,
instead of getOption("keep.source.pkgs") and
getOption("keep.parse.data.pkgs")
toplevel.env is set to getOption("topLevelEnvironment", envir). In
other words, if the option topLevelEnvironment is already set, it is
respected.
The environment envir, invisibly.
base::library()
This function is documented but not exported. Reach in with
envir:::set_library_default_pos() to use it.
set_library_default_pos(..., after = NULL, before = NULL, value = NULL)set_library_default_pos(..., after = NULL, before = NULL, value = NULL)
... |
Ignored. Arguments must be named |
after, before
|
string; the name of the environment on the search path that library() calls should by default attach after or before. |
value |
The value (or quoted expression) the new argument should be. |
This is primarily a way to "pin" a particular environment on the
search path. For example, say you have a "project_utils" environment where
you've defined a variety of useful functions. To prevent future library()
calls from masking any objects in your attached "project_utils"
environment, you can modify the default pos argument to library.
attach_source("project_utils.R", name = "project_utils)
set_library_default_pos(after = "project_utils")
library(foo) # now foo will attach after the "project_utils" environment
The original default value of pos, invisibly
within methods for R environmentswithin methods for R environments
## S3 method for class 'environment' within(data, expr, ..., quote = substitute(expr)) ## S3 method for class 'character' within( data, expr, ..., pos = 2L, warn.conflicts = TRUE, mask.ok = NULL, quote = substitute(expr) )## S3 method for class 'environment' within(data, expr, ..., quote = substitute(expr)) ## S3 method for class 'character' within( data, expr, ..., pos = 2L, warn.conflicts = TRUE, mask.ok = NULL, quote = substitute(expr) )
data |
An R environment, or the name of a (potentially new) attached environment. |
expr |
The bare R expression to evaluate. Automatically quoted. |
... |
Ignored. Added for compatibility with the S3 generic. Throws an
error if any arguments are passed to |
quote |
An R language object. This is an escape hatch from the automatic
quoting of |
pos |
The position where to attach the environment, if creating a new
one. If an environment of |
warn.conflicts |
logical. If TRUE (the default), print warnings about objects in the attached environment that that are masking or masked by other objects of the same name. |
mask.ok |
character vector of names of objects that can mask objects on
the search path without signaling a warning if |
The only difference between attach_eval and within.character is
the order of the arguments and the return value; the first
returns the result of evaluating the expression, the latter the
environment.
The R environment, invisibly.
See the note in attach_source about a potential pitfall of evaluating
code directly in an attached environment.
attach_eval attach_source eval within