Title: | Unpacking Assignment for Lists via Pattern Matching |
---|---|
Description: | Provides an operator for assigning nested components of a list to names via a concise pattern matching syntax. This is especially convenient for assigning individual names to the multiple values that a function may return in the form of a list, and for extracting deeply nested list components. |
Authors: | Eugene Ha [aut, cre] |
Maintainer: | Eugene Ha <[email protected]> |
License: | MIT + file LICENSE |
Version: | 0.2.0.9000 |
Built: | 2024-11-27 05:40:19 UTC |
Source: | https://github.com/egnha/dub |
The %<<-%
operator assigns multiple (nested) components of a list or vector
to names via pattern matching (“unpacking assignment”). Think of the
“dub(ble) arrow” <<-
as a pictograph representing multiple <-
's.
%<<-%
is especially convenient for:
assigning individual names to the multiple values that a function may return in the form of a list;
extracting deeply nested list components.
pattern %<<-% value value %->>% pattern
pattern %<<-% value value %->>% pattern
pattern |
Pattern of names that the components of |
value |
List or vector. |
Returns value
invisibly.
Names are matched to the (nested) components of a list using a concise pattern matching syntax that mirrors the structure of the list. Apart from names, the syntax consists of two classes of symbols:
List constructors — Use a pair of parentheses to indicate a list, and a colon, rather than a comma, to indicate successive names.
Wildcards — Use a dot (.
) to skip assignment of a specific
component, or dots (...
) to skip assignment of a range of components.
See the examples for an illustration of common use cases.
Unpacking/multiple assignment appears in other
languages (e.g.,
Python,
JavaScript,
Clojure).
While R has no such feature, using a custom operator to do this has long
been a folklore method. An early implementation is due to
Gabor Grothendieck
(2004), cf. list
in the
gsubfn package.
# Assign successive components (one : two : three) %<<-% list(1, 2, 3) stopifnot(one == 1, two == 2, three == 3) # Assign nested components (p : (q : r : (s : t))) %<<-% list(1, list(2, 3, list(4, 5))) (P : (Q : R : S)) %<<-% list(1, list(2, 3, list(4, 5))) stopifnot(p == 1, q == 2, r == 3, s == 4, t == 5, P == 1, Q == 2, R == 3, identical(S, list(4, 5))) # Unpack nested components with nested parentheses (w) %<<-% list(1:3) (((z))) %<<-% list(list(list("z"))) ((x : y)) %<<-% list(list("x", "y")) stopifnot(w == 1:3, x == "x", y == "y", z == "z") # Skip a component with a dot (.) (a : . : b) %<<-% list("a", "skip this", "b") ((c : .) : .) %<<-% list(list("c", "skip this"), "skip this") stopifnot(a == "a", b == "b", c == "c") # Skip a range of components with dots (...) (first : ... : last) %<<-% letters (. : second : ...) %<<-% letters (mpg : cyl : ...) %<<-% mtcars stopifnot( first == "a", second == "b", last == "z", mpg == mtcars$mpg, cyl == mtcars$cyl )
# Assign successive components (one : two : three) %<<-% list(1, 2, 3) stopifnot(one == 1, two == 2, three == 3) # Assign nested components (p : (q : r : (s : t))) %<<-% list(1, list(2, 3, list(4, 5))) (P : (Q : R : S)) %<<-% list(1, list(2, 3, list(4, 5))) stopifnot(p == 1, q == 2, r == 3, s == 4, t == 5, P == 1, Q == 2, R == 3, identical(S, list(4, 5))) # Unpack nested components with nested parentheses (w) %<<-% list(1:3) (((z))) %<<-% list(list(list("z"))) ((x : y)) %<<-% list(list("x", "y")) stopifnot(w == 1:3, x == "x", y == "y", z == "z") # Skip a component with a dot (.) (a : . : b) %<<-% list("a", "skip this", "b") ((c : .) : .) %<<-% list(list("c", "skip this"), "skip this") stopifnot(a == "a", b == "b", c == "c") # Skip a range of components with dots (...) (first : ... : last) %<<-% letters (. : second : ...) %<<-% letters (mpg : cyl : ...) %<<-% mtcars stopifnot( first == "a", second == "b", last == "z", mpg == mtcars$mpg, cyl == mtcars$cyl )