Type: Package
Title: Multiple, Unpacking, and Destructuring Assignment
Version: 0.2.0
Description: Provides a %<-% operator to perform multiple, unpacking, and destructuring assignment in R. The operator unpacks the right-hand side of an assignment into multiple values and assigns these values to variables on the left-hand side of the assignment.
URL: https://github.com/r-lib/zeallot
BugReports: https://github.com/r-lib/zeallot/issues
License: MIT + file LICENSE
Encoding: UTF-8
RoxygenNote: 7.3.2
VignetteBuilder: knitr
Depends: R (≥ 3.2)
Suggests: codetools, testthat, knitr, rmarkdown, purrr
NeedsCompilation: no
Packaged: 2025-05-22 07:55:46 UTC; nteetor
Author: Nathan Teetor [aut, cre], Paul Teetor [ctb]
Maintainer: Nathan Teetor <nate@haufin.ch>
Repository: CRAN
Date/Publication: 2025-05-27 10:00:02 UTC

Multiple, unpacking, and destructuring assignment in R

Description

zeallot provides a %<-% operator to perform multiple assignment in R. To get started with zeallot be sure to read over the introductory vignette on unpacking assignment, vignette('unpacking-assignment').

Author(s)

Maintainer: Nathan Teetor nate@haufin.ch

Other contributors:

See Also

%<-%


Destructure an object

Description

destructure is used during unpacking assignment to coerce an object into a list. Individual elements of the list are assigned to names on the left-hand side of the unpacking assignment expression.

Usage

destructure(x)

## S3 method for class 'data.frame'
destructure(x)

## S3 method for class 'summary.lm'
destructure(x)

## Default S3 method:
destructure(x)

Arguments

x

An R object.

Details

New implementations of destructure can be very simple. A new destructure implementation might only strip away the class of a custom object and return the underlying list structure. Alternatively, an object might destructure into a nested set of values and may require a more complicated implementation. In either case, new implementations must return a list object so %<-% can handle the returned value(s).

See Also

%<-%

Examples


# Data frames become a list of columns
destructure(faithful)

# A simple shape class
shape <- function(sides = 4, color = "red") {
  structure(
    list(sides = sides, color = color),
    class = "shape"
  )
}

## Not run: 
# Cannot destructure the shape object _yet_
c(sides, color) %<-% shape()

## End(Not run)

# Implement a new destructure method for the shape class
destructure.shape <- function(x) {
  unclass(x)
}

# Now we can destructure shape objects
c(sides, color) %<-% shape()

c(sides, color) %<-% shape(3, "green")


Multiple assignment operators

Description

Assign values to name(s).

Usage

x %<-% value

value %->% x

Arguments

x

A name structure, see section below.

value

A list of values, vector of values, or R object to assign.

Value

%<-% and %->% invisibly return value.

These operators are used primarily for their assignment side-effect. %<-% and %->% assign into the environment in which they are evaluated.

Name Structure

The basics

At its simplest, the name structure is a single variable name, in which case %<-% and %->% perform regular assignment, x %<-% list(1, 2, 3) or list(1, 2, 3) %->% x.

To specify multiple variable names use c(), for example c(x, y, z) %<-% c(1, 2, 3).

When value is neither an atomic vector nor a list, %<-% and %->% will try to destructure value into a list before assigning variables, see destructure().

In-place assignment

One may also assign into a list or environment, c(x, x[[1]]) %<-% list(list(), 1).

Nested names

One can also nest calls to c(), c(x, c(y, z)). This nested structure is used to unpack nested values, c(x, c(y, z)) %<-% list(1, list(2, 3)).

Collector variables

To gather extra values from the beginning, middle, or end of value use a collector variable. Collector variables are indicated with the .. prefix, c(..x, y) %<-% list(1, 2, 3, 4).

Skipping values

Use . in place of a variable name to skip a value without raising an error or assigning the value, c(x, ., z) %<-% list(1, 2, 3).

Use .. to skip multiple values without raising an error or assigning the values, c(w, .., z) %<-% list(1, NA, NA, 4).

Default values

Use = with a value to specify a default value for a variable, c(x, y = NULL) %<-% list(1).

Unfortunately, using a default value with in-place assignment raises an error because of R's syntax, c(x, x[[1]] = 1) %<-% list(list()).

Named assignment

Use = without a value to assign values by name, c(two=) %<-% list(one = 1, two = 2, three = 3).

See Also

For more on unpacking custom objects please refer to destructure().

Examples

# Basic usage
c(x, y) %<-% list(0, 1)

# Unpack and assign nested values
c(c(x, y), z) %<-% list(list(2, 3), list(3, 4))

# Assign columns of data frame
c(eruptions, waiting) %<-% faithful

# Assign specific columns by name
c(mpg=, hp=, gear=) %<-% mtcars

# Alternatively, assign a column by position
c(first_col, .., last_col) %<-% mtcars

# Skip initial values, assign final value
todo_list <- list("1. Make food", "2. Pack lunch", "3. Save world")

c(.., final_todo) %<-% todo_list

# Assign first name, skip middle initial, assign last name
c(first_name, ., last_name) %<-% c("Ursula", "K", "Le Guin")

# Unpack nested values w/ nested names
fibs <- list(1, list(2, list(3, list(5))))

c(f2, c(f3, c(f4, c(f5)))) %<-% fibs

# Unpack first numeric, leave rest
c(f2, ..rest) %<-% unlist(fibs)

# Swap values without using temporary variables
c(a, b) %<-% c("eh", "bee")

c(a, b) %<-% c(b, a)

# Handle missing values with default values
parse_time <- function(x) {
  strsplit(x, " ")[[1]]
}

c(hour, period = NA) %<-% parse_time("10:00 AM")

c(hour, period = NA) %<-% parse_time("15:00")

# Right operator
list(1, 2, "a", "b", "c") %->% c(x, y, ..z)


Allow zeallous assignment

Description

Using zeallot within an R package may cause ⁠R CMD check⁠ to raise NOTEs concerning variables with "no visible binding". To avoid these NOTEs, include a call to zeallous() in a package's .onLoad() function.

Usage

zeallous()

Details

The ⁠R CMD check⁠ process uses a package {codetools} to check for assigned variables. However, due to the non-standard nature of zeallot assignment the codetools package does not identify these variables. To work around this, the zeallous() function modifies the variables found by codetools to avoid the NOTEs raised by ⁠R CMD check⁠.

Examples


.onLoad <- function(libname, pkgname) {
  zeallous()
}