| Title: | Isolate Functions for Remote Execution |
|---|---|
| Description: | Sending functions to remote processes can be wasteful of resources because they carry their environments with them. With the carrier package, it is easy to create functions that are isolated from their environment. These isolated functions, also called crates, print at the console with their total size and can be easily tested locally before being sent to a remote. |
| Authors: | Lionel Henry [aut, cre], Posit Software, PBC [cph, fnd] (ROR: <https://ror.org/03wc8by49>) |
| Maintainer: | Lionel Henry <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.3.0.9000 |
| Built: | 2026-10-11 11:33:37 UTC |
| Source: | https://github.com/r-lib/carrier |
crate() creates functions in a self-contained environment
(technically, a child of the base environment). This has two
advantages:
They can easily be executed in another process.
Their effects are reproducible. You can run them locally with the same results as on a different process.
Creating self-contained functions requires some care, see section below.
crate( .fn, ..., .parent_env = baseenv(), .error_arg = ".fn", .error_call = environment() )crate( .fn, ..., .parent_env = baseenv(), .error_arg = ".fn", .error_call = environment() )
.fn |
A formula or function. The function may be defined
inside the call to
Formulas are converted to purrr-like lambda functions using
|
... |
Named arguments to declare in the environment of |
.parent_env |
The default of |
.error_arg |
An argument name as a string. This argument will be mentioned in error messages as the input that is at the origin of a problem. |
.error_call |
The execution environment of a currently
running function, e.g. |
They should call package functions with an explicit ::
namespace. This includes packages in the default search path with
the exception of the base package. For instance var() from the
stats package must be called with its namespace prefix:
stats::var(x).
They should declare any data they depend on. You can declare data
by supplying additional arguments or by unquoting objects with !!.
A function (closure) supplied as an additional argument is itself crated.
This means that it must be self-contained by supplying all objects required
by it as further additional arguments, if not already supplied. Only
functions directly supplied to ... are crated, and containers such as
lists are not recursively walked to find functions. Note that if an
existing crate is supplied, this is not re-crated.
# You can create functions using the ordinary notation: crate(\(x) stats::var(x)) # Or the formula notation: crate(~ stats::var(.x)) # Declare data by supplying named arguments. You can test you have # declared all necessary data by calling your crated function: na_rm <- TRUE fn <- crate(~ stats::var(.x, na.rm = na_rm)) try(fn(1:10)) # Declare `na_rm` by passing it as a named argument: fn <- crate(~ stats::var(.x, na.rm = na_rm), na_rm = na_rm) fn(1:10) # The size of each declared object is shown in the crate printout: fn # You can also pass an already defined function. Its enclosing # environment is replaced with the crate's evaluation environment, # so any data it depends on must be declared via `...`: fn <- function(x) toupper(x) crate(fn) # For the same reason, existing functions that depend on state # captured in their environment, such as those created by function # factories, lose that state and fail when called: fn <- stats::ecdf(1:10) crated <- crate(fn) try(crated(5)) # Instead, construct the function within the crate: crated <- crate(\(x) stats::ecdf(1:10)(x)) crated(5)# You can create functions using the ordinary notation: crate(\(x) stats::var(x)) # Or the formula notation: crate(~ stats::var(.x)) # Declare data by supplying named arguments. You can test you have # declared all necessary data by calling your crated function: na_rm <- TRUE fn <- crate(~ stats::var(.x, na.rm = na_rm)) try(fn(1:10)) # Declare `na_rm` by passing it as a named argument: fn <- crate(~ stats::var(.x, na.rm = na_rm), na_rm = na_rm) fn(1:10) # The size of each declared object is shown in the crate printout: fn # You can also pass an already defined function. Its enclosing # environment is replaced with the crate's evaluation environment, # so any data it depends on must be declared via `...`: fn <- function(x) toupper(x) crate(fn) # For the same reason, existing functions that depend on state # captured in their environment, such as those created by function # factories, lose that state and fail when called: fn <- stats::ecdf(1:10) crated <- crate(fn) try(crated(5)) # Instead, construct the function within the crate: crated <- crate(\(x) stats::ecdf(1:10)(x)) crated(5)
Is an object a crate?
is_crate(x)is_crate(x)
x |
An object to test. |