README.md

staticimports

R-CMD-check

staticimports makes it easy to statically import functions into R projects or packages. The “static” importing means that the functions are copied into the project as text, instead of being loaded from a separate package at run time.

The benefits of doing things this way:

Where can statically imported functions come from?

Instead of copying and pasting utility functions from project to project, the utility functions can be centralized in a place where they can be vetted and tested.

The functions in staticimports are designed to be:

If your project imports a function from staticimports, and that function changes in a way that has a negative impact on your project, you can simply stop importing it from staticimports, and copy the old version to a separate file.

Installation

You can install the development version of staticimports with:

remotes::install_github("wch/staticimports")

Usage

To use, put a comment block starting with # @staticimports in one of your R source files. For example, your utils.R may have this at the top:

# @staticimports pkg:staticimports
#  os_name %||%
#  map walk

The pkg:staticimports tells it to import from staticimports package. To import from a different package, use pkg:mypackage. It looks in a directory of the package named staticexports to find the objects. To import from a local absolute or relative path, you can use something like @staticimports ../r_utils/.

The following lines name the objects to import from the source. In this case, they are os_name, %||%, map, and walk.

To perform the import, run:

library(staticimports)
import()

By default this will write the functions to a file R/staticimports.R in your project.

You examine the output by writing to stdout() instead of R/staticimports.R. Notice how importing os_name automatically brings in is_windows, is_mac, and is_linux.

import(outfile = stdout())
#> # Generated by staticimports; do not edit by hand.
#> # ======================================================================
#> 
#> `%||%` <- function(a, b) {
#>   if (is.null(a)) b else a
#> }
#> 
#> is_linux   <- function() Sys.info()[['sysname']] == 'Linux'
#> 
#> is_mac     <- function() Sys.info()[['sysname']] == 'Darwin'
#> 
#> is_windows <- function() .Platform$OS.type == "windows"
#> 
#> map <- function(.x, .f, ...) {
#>   lapply(.x, .f, ...)
#> }
#> 
#> os_name <- function() {
#>   if (is_windows()) {
#>     "win"
#>   } else if (is_mac()) {
#>     "mac"
#>   } else if (is_linux()) {
#>     "linux"
#>   } else if (.Platform$OS.type == "unix") {
#>     "unix"
#>   } else {
#>     "unknown"
#>   }
#> }
#> 
#> walk <- function(.x, .f, ...) {
#>   for (i in seq_along(.x)) {
#>     .f(.x[[i]], ...)
#>   }
#>   NULL
#> }

For testing what the output will look like, you can use import_objs() to see what it looks like when you import specific objects by name:

import_objs(c("map", "walk"), outfile = stdout())
#> # Generated by staticimports; do not edit by hand.
#> # ======================================================================
#> 
#> map <- function(.x, .f, ...) {
#>   lapply(.x, .f, ...)
#> }
#> 
#> walk <- function(.x, .f, ...) {
#>   for (i in seq_along(.x)) {
#>     .f(.x[[i]], ...)
#>   }
#>   NULL
#> }

Under the hood

The functions provided by staticimports are in the inst/staticexports directory of the repository. When import() is called, it sources all of those files into a new environment. Then it finds all the internal dependencies among those functions. If a function fn_a is requested, and it uses a function fn_b, then both of those functions will be copied to the project.

If a different set of source files is used, it sources all of the files in the target directory into a new environment and then proceeds the same way.

TODO



wch/staticimports documentation built on Jan. 13, 2024, 8:48 p.m.