All Projects → HenrikBengtsson → listenv

HenrikBengtsson / listenv

Licence: other
R package: Environments Behaving As Lists

Programming Languages

r
7636 projects
Makefile
30231 projects

Labels

Projects that are alternatives of or similar to listenv

Dynamic-Parkour-System
Dynamic Parkour System is a FREE plugin for Unity that allows anyone to import any model and have an already working controller with parkour capabilities like in Assassin's Creed games.
Stars: ✭ 694 (+3370%)
Mutual labels:  package
flutter background
A flutter plugin to keep apps running in the background via foreground services. Currently Android only.
Stars: ✭ 58 (+190%)
Mutual labels:  package
eerie
The package manager for Io.
Stars: ✭ 22 (+10%)
Mutual labels:  package
FinMesh
A python package that brings together financial and economic data.
Stars: ✭ 20 (+0%)
Mutual labels:  package
emacs-hacker-typer
A customizable implementation of http://hackertyper.com in emacs.
Stars: ✭ 21 (+5%)
Mutual labels:  package
toggler
Atom plugin - Toggle words and symbols
Stars: ✭ 21 (+5%)
Mutual labels:  package
SwiftPackage
🏆 Template to make a Swift package
Stars: ✭ 37 (+85%)
Mutual labels:  package
macpack
Makes a macOS binary redistributable by searching the dependency tree and copying/patching non-system libraries.
Stars: ✭ 20 (+0%)
Mutual labels:  package
parse it
A python library for parsing multiple types of config files, envvars & command line arguments that takes the headache out of setting app configurations.
Stars: ✭ 86 (+330%)
Mutual labels:  package
pfSense-pkg-WireGuard
This is a port of the original WireGuard UI bits as implemented by Netgate in pfSense 2.5.0 to a package suitable for rapid iteration and more frequent updating on future releases of pfSense.
Stars: ✭ 194 (+870%)
Mutual labels:  package
meteor-graphql
Compiler plugin that supports GraphQL files in Meteor
Stars: ✭ 56 (+180%)
Mutual labels:  package
elm-generative
Making generative art in Elm
Stars: ✭ 23 (+15%)
Mutual labels:  package
devliver
Your private self hosted composer repository with user management
Stars: ✭ 50 (+150%)
Mutual labels:  package
laravel-circuit-breaker
An implementation of the circuit breaker pattern for Laravel 5.6
Stars: ✭ 26 (+30%)
Mutual labels:  package
Odapter
C# code generator for Oracle packages
Stars: ✭ 16 (-20%)
Mutual labels:  package
telegram
📚 Golang bindings for Telegram API
Stars: ✭ 15 (-25%)
Mutual labels:  package
future.mapreduce
[EXPERIMENTAL] R package: future.mapreduce - Utility Functions for Future Map-Reduce API Packages
Stars: ✭ 12 (-40%)
Mutual labels:  package
flutter web import js library
Import & use javascript libraries in your flutter web projects
Stars: ✭ 28 (+40%)
Mutual labels:  package
laravel-repoman
Set a payment deadline for the customer
Stars: ✭ 14 (-30%)
Mutual labels:  package
packager
Laravel Package Skeleton Generator - https://youtu.be/kQRQWzDEbGk
Stars: ✭ 20 (+0%)
Mutual labels:  package
CRAN check status R CMD check status Coverage Status

listenv: Environments Behaving (Almost) as Lists

Summary

List environments are environments that have list-like properties. They are implemented by the listenv package. The main features of a list environment are summarized in the below table:

Property list environments lists environments
Number of elements, e.g. length() yes yes yes
Named elements, e.g. names(), x$a and x[["a"]] yes yes yes
Duplicated names yes yes
Element names are optional yes yes
Indexed elements, e.g. x[[4]] yes yes
Dimensions, e.g. dim(x), t(x), and aperm(x, c(3,1,2)) yes yes
Names of dimensions, e.g. dimnames(x) yes yes
Indexing by dimensions, e.g. x[[2, 4]] and x[[2, "D"]] yes yes
Multi-element subsetting, e.g. x[c("a", "c")], x[-1] and x[2:1, , 3] yes yes
Multi-element subsetting preserves element names yes
Resizing, e.g. length(x) <- 6 yes yes
Removing elements by assigning NULL, e.g. x$c <- NULL and x[1:3] <- NULL yes yes
Removing parts of dimensions by assigning NULL, e.g. x[,2] <- NULL yes
Mutable, e.g. y <- x; y$a <- 3; identical(y, x) yes yes
Compatible* with assign(), delayedAssign(), get() and exists() yes yes

For example,

> x <- listenv(a = 1, b = 2, c = "hello")
> x
A 'listenv' vector with 3 elements ('a', 'b', 'c').
> length(x)
[1] 3
> names(x)
[1] "a" "b" "c"
> x$a
[1] 1
> x[[3]] <- toupper(x[[3]])
> x$c
[1] "HELLO"
> y <- x
> y$d <- y$a + y[["b"]]
> names(y)[2] <- "a"
> y$a
[1] 1
> y
A 'listenv' vector with 4 elements ('a', 'a', 'c', 'd').
> identical(y, x)
[1] TRUE
> for (ii in seq_along(x)) {
+     cat(sprintf("Element %d (%s): %s\n", ii, sQuote(names(x)[ii]), 
+         x[[ii]]))
+ }
Element 1 ('a'): 1
Element 2 ('a'): 2
Element 3 ('c'): HELLO
Element 4 ('d'): 3
> x[c(1, 3)] <- list(2, "Hello world!")
> x
A 'listenv' vector with 4 elements ('a', 'a', 'c', 'd').
> y <- as.list(x)
> str(y)
List of 4
 $ a: num 2
 $ a: num 2
 $ c: chr "Hello world!"
 $ d: num 3
> z <- as.listenv(y)
> z
A 'listenv' vector with 4 elements ('a', 'a', 'c', 'd').
> identical(z, x)
[1] FALSE
> all.equal(z, x)
[1] TRUE

Creating list environments

List environments are created similarly to lists but also similarly to environments. To create an empty list environment, use

> x <- listenv()
> x
A 'listenv' vector with 0 elements (unnamed).

This can later can be populated using named assignments,

> x$a <- 1
> x
A 'listenv' vector with 1 element ('a').

comparable to how both lists and environments work. Similarly to lists, they can also be populated using indices, e.g.

> x[[2]] <- 2
> x$c <- 3
> x
A 'listenv' vector with 3 elements ('a', '', 'c').

Just as for lists, a list environment is expanded with NULL elements whenever a new element is added that is beyond the current length plus one, e.g.

> x[[5]] <- 5
> x
A 'listenv' vector with 5 elements ('a', '', 'c', '', '').
> x[[4]]
NULL

As with lists, the above list environment can also be created from the start, e.g.

> x <- listenv(a = 1, 3, c = 4, NULL, 5)
> x
A 'listenv' vector with 5 elements ('a', '', 'c', '', '').

As for lists, the length of a list environment can at any time be increased or decreased by assigning it a new length. If decreased, elements are dropped, e.g.

> x
A 'listenv' vector with 5 elements ('a', '', 'c', '', '').
> length(x) <- 2
> x
A 'listenv' vector with 2 elements ('a', '').
> x[[1]]
[1] 1
> x[[2]]
[1] 3

If increased, new elements are populated with unnamed elements of NULL, e.g.

> length(x) <- 4
> x
A 'listenv' vector with 4 elements ('a', '', '', '').
> x[[3]]
NULL
> x[[4]]
NULL

To allocate an "empty" list environment (with all NULL:s) of a given length, do

> x <- listenv()
> length(x) <- 4
> x
A 'listenv' vector with 4 elements (unnamed).

Note: Unfortunately, it is not possible to use x <- vector("listenv", length = 4); that construct is only supported for the basic data types.

Elements can be dropped by assigning NULL, e.g. to drop the first and third element of a list environment, do:

> x[c(1, 3)] <- NULL
> x
A 'listenv' vector with 2 elements (unnamed).

Iterating over elements

Iterating over elements by names

Analogously to lists and plain environments, it is possible to iterate over elements of list environments by the element names. For example,

> x <- listenv(a = 1, b = 2, c = 3)
> for (name in names(x)) {
+     cat(sprintf("Element %s: %s\n", sQuote(name), x[[name]]))
+ }
Element 'a': 1
Element 'b': 2
Element 'c': 3

Iterating over elements by indices

Analogously to lists, but contrary to plain environments, it is also possible to iterate over elements by their indices. For example,

> x <- listenv(a = 1, b = 2, c = 3)
> for (ii in seq_along(x)) {
+     cat(sprintf("Element %d: %s\n", ii, x[[ii]]))
+ }
Element 1: 1
Element 2: 2
Element 3: 3

Coercion to and from list environments

Coercing to lists and vectors

Coercing a list environment to a list:

> x <- listenv(a = 2, b = 3, c = "hello")
> x
A 'listenv' vector with 3 elements ('a', 'b', 'c').
> y <- as.list(x)
> str(y)
List of 3
 $ a: num 2
 $ b: num 3
 $ c: chr "hello"

Coercing a list to a list environment:

> z <- as.listenv(y)
> z
A 'listenv' vector with 3 elements ('a', 'b', 'c').
> identical(z, x)
[1] FALSE
> all.equal(z, x)
[1] TRUE

Unlisting:

> unlist(x)
      a       b       c 
    "2"     "3" "hello" 
> unlist(x[-3])
a b 
2 3 
> unlist(x[1:2], use.names = FALSE)
[1] 2 3

Multi-dimensional list environments

Analogously to lists, and contrary to plain environments, list environments can have dimensions with corresponding names. For example,

> x <- as.listenv(1:6)
> dim(x) <- c(2, 3)
> dimnames(x) <- list(c("a", "b"), c("A", "B", "C"))
> x
A 'listenv' matrix with 6 elements (unnamed) arranged in 2x3 rows ('a', 'b') and columns ('A', 'B', 'C').

An easy way to quickly get an overview is to coerce to a list, e.g.

> as.list(x)
  A B C
a 1 3 5
b 2 4 6

Individual elements of a list environment can be accessed using standard subsetting syntax, e.g.

> x[["a", "B"]]
[1] 3
> x[[1, 2]]
[1] 3
> x[[1, "B"]]
[1] 3

We can assign individual elements similarly, e.g.

> x[["b", "B"]] <- -x[["b", "B"]]
> as.list(x)
  A B  C
a 1 3  5
b 2 -4 6

We can also assign multiple elements through dimensional subsetting, e.g.

> x[2, -1] <- 98:99
> as.list(x)
  A B  C 
a 1 3  5 
b 2 98 99
> x["a", c(1, 3)] <- list(97, "foo")
> as.list(x)
  A  B  C    
a 97 3  "foo"
b 2  98 99   
> x[] <- 1:6
> as.list(x)
  A B C
a 1 3 5
b 2 4 6

Concurrently with dimensional names it is possible to have names of the individual elements just as for list environments without dimensions. For example,

> names(x) <- letters[seq_along(x)]
> x
A 'listenv' matrix with 6 elements ('a', 'b', 'c', ..., 'f') arranged in 2x3 rows ('a', 'b') and columns ('A', 'B', 'C').
> x[["a"]]
[1] 1
> x[["f"]]
[1] 6
> x[c("a", "f")]
A 'listenv' vector with 2 elements ('a', 'f').
> unlist(x)
a b c d e f 
1 2 3 4 5 6 
> as.list(x)
  A B C
a 1 3 5
b 2 4 6
attr(,"names")
[1] "a" "b" "c" "d" "e" "f"

Contrary to lists, element names are preserved also with multi-dimensional subsetting, e.g.

> x[1, 2]
A 'listenv' vector with 1 element ('c').
> x[1, 2, drop = FALSE]
A 'listenv' matrix with 1 element ('c') arranged in 1x1 rows ('a') and columns ('B').
> x[1:2, 2:1]
A 'listenv' matrix with 4 elements ('c', 'd', 'a', 'b') arranged in 2x2 rows ('a', 'b') and columns ('B', 'A').
> x[2, ]
A 'listenv' vector with 3 elements ('b', 'd', 'f').
> x[2, , drop = FALSE]
A 'listenv' matrix with 3 elements ('b', 'd', 'f') arranged in 1x3 rows ('b') and columns ('A', 'B', 'C').
> x["b", -2, drop = FALSE]
A 'listenv' matrix with 2 elements ('b', 'f') arranged in 1x2 rows ('b') and columns ('A', 'C').

Note, whenever dimensions are set using dim(x) <- dims both the dimensional names and the element names are removed, e.g.

> dim(x) <- NULL
> names(x)
NULL

This behavior is by design, cf. help("dim", package="base").

To allocate an "empty" list environment array (with all NULL:s) of a given dimension, do

> x <- listenv()
> dim(x) <- c(2, 3)
> dimnames(x) <- list(c("a", "b"), c("A", "B", "C"))
> x
A 'listenv' matrix with 6 elements (unnamed) arranged in 2x3 rows ('a', 'b') and columns ('A', 'B', 'C').

Rows and columns can be dropped by assigning NULL, e.g. to drop the first and third column of a list-environment matrix, do:

> x[, c(1, 3)] <- NULL
> x
A 'listenv' matrix with 2 elements (unnamed) arranged in 2x1 rows ('a', 'b') and columns ('B').

Important about environments

List environments are as their name suggests environments. Whenever working with environments in R, it is important to understand that environments are mutable whereas all other of the basic data types in R are immutable. For example, consider the following function that assigns zero to element a of object x:

> setA <- function(x) {
+     x$a <- 0
+     x
+ }

If we pass a regular list to this function,

> x <- list(a = 1)
> y <- setA(x)
> x$a
[1] 1
> y$a
[1] 0

we see that x is unaffected by the assignment. This is because lists are immutable in R. However, if we pass an environment instead,

> x <- new.env()
> x$a <- 1
> y <- setA(x)
> x$a
[1] 0
> y$a
[1] 0

we find that x was affected by the assignment. This is because environments are mutable in R. Since list environments inherits from environments, this also goes for them, e.g.

> x <- listenv(a = 1)
> y <- setA(x)
> x$a
[1] 0
> y$a
[1] 0

What is also important to understand is that it is not just the content of an environment that is mutable but also its attributes. For example,

> x <- listenv(a = 1)
> y <- x
> attr(y, "foo") <- "Hello!"
> attr(x, "foo")
[1] "Hello!"

More importantly, since dimensions and their names are also attributes, this also means they are mutable. For example,

> x <- as.listenv(1:6)
> dim(x) <- c(2, 3)
> x
A 'listenv' matrix with 6 elements (unnamed) arranged in 2x3 unnamed rows and columns.
> y <- x
> dim(y) <- c(3, 2)
> x
A 'listenv' matrix with 6 elements (unnamed) arranged in 3x2 unnamed rows and columns.

Installation

R package listenv is available on CRAN and can be installed in R as:

install.packages("listenv")

Pre-release version

To install the pre-release version that is available in Git branch develop on GitHub, use:

remotes::install_github("HenrikBengtsson/listenv", ref="develop")

This will install the package from source.

Contributing

To contribute to this package, please see CONTRIBUTING.md.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].