# Use container in interactive session

## Interactive usage

In an interactive R session a {container} can be used similar to a base R `list`, but also provides some extra features. For easier typing it’s recommended to use the shorter `cont`.

    library(container)
    co <- cont(a = 1, b = 1:10)  # same as co = container(a = 1, b = 1:10)

The {container} print method is designed to be very compact.

    print(co)
    # [a = 1, b = (1L 2L 3L 4L ...)]

For more verbose output, either convert to a base `list` …

    as.list(co)
    # $a
    # [1] 1
    #
    # $b
    #  [1]  1  2  3  4  5  6  7  8  9 10

or use `str`.

    str(co)
    # Container of 2
    #  $ a: num 1
    #  $ b: int [1:10] 1 2 3 4 5 6 7 8 9 10

Both `length` and `names` work as usual.

    length(co)
    # [1] 2

    names(co)
    # [1] "a" "b"

    names(co)[1] <- "A"

    co
    # [A = 1, b = (1L 2L 3L 4L ...)]

A {container} object can also be constructed from a list.

    l <- list(x = (1:2)^1, y = (1:2)^2)
    co2 <- as.container(l)

    co2
    # [x = (1 2), y = (1 4)]

### Add

Elements can be added by concatenation,

    c(co, c = 3, d = 4)
    # [A = 1, b = (1L 2L 3L 4L ...), c = 3, d = 4]

    c(co, co2)
    # [A = 1, b = (1L 2L 3L 4L ...), x = (1 2), y = (1 4)]

or name,

    co[["c"]] <- 3

    co
    # [A = 1, b = (1L 2L 3L 4L ...), c = 3]

and containers can be nested.

    co[["co2"]] <- co2

    co
    # [A = 1, b = (1L 2L 3L 4L ...), c = 3, co2 = [x = (1 2), y = (1 4)]]

In contrast to base R `list`, elements cannot be added via positional index if it exceeds the container’s length.

    co[[5]] <- 5
    # Error: index out of range (length = 4): 5

### Replace

Single or multiple value replacement works as usual.

    co[[3]] <- 0
    co[1:2] <- 0

    co
    # [A = 0, b = 0, c = 0, co2 = [x = (1 2), y = (1 4)]]

Note that assigning `NULL` does not remove the element, but just replaces its value with `NULL`.

    co[["A"]] <- NULL

    co
    # [A = NULL, b = 0, c = 0, co2 = [x = (1 2), y = (1 4)]]

In contrast to base `list`, containers can take a mix of numeric and character indices.

    co[list("A", 2, "c")] <- list(1, 2, "three")

    co
    # [A = 1, b = 2, c = "three", co2 = [x = (1 2), y = (1 4)]]

Another option is to replace by value.

    co[[{"three"}]] <- 3

    co
    # [A = 1, b = 2, c = 3, co2 = [x = (1 2), y = (1 4)]]

This works for any data type.

    co[[{co2}]] <- 4

    co
    # [A = 1, b = 2, c = 3, co2 = 4]

### Extract

#### Basic extraction

The following standard access operators as known from base R can be applied.

    co <- container(a = 1, b = "b", c = 3, d = "d")
    co[["a"]]
    # [1] 1

    co[[1]]
    # [1] 1

    co[1:3]
    # [a = 1, b = "b", c = 3]

Negative indices (since version 1.1.0) also work as expected.

    co[-1]
    # [b = "b", c = 3, d = "d"]

    co[-(1:3)]
    # [d = "d"]

Due to {container} object under the hood being an environment, the `$` operator is not supported for extraction (it usually just yields `NULL`). As a workaround, you could transform to a list first.

    co$a
    # NULL

    li <- as.list(co)
    li$a
    # [1] 1

#### More extraction features

The {container} package introduces a variety of additional extraction capabilities to make working with containers in interactive sessions even more user-friendly.

First of all, multiple indices can be provided as separate arguments, that is, without having to wrap them in `c()`.

    co[1, 3, 4]
    # [a = 1, c = 3, d = "d"]

    co[TRUE, FALSE]
    # [a = 1, c = 3]

    co["c", "b", "a"]
    # [c = 3, b = "b", a = 1]

Second, indices can be mixed, in a list or, again, as separate arguments.

    co[list(1, "b", 4)]
    # [a = 1, b = "b", d = "d"]

    co[1, "b", 4]
    # [a = 1, b = "b", d = "d"]

##### Extract and replace ranges (since version 1.1.0)

Since version 1.1.0, non-standard evaluation of indices is available, which allows easy definitions of ranges using numbers, unquoted names or both.

    co[a:c]
    # [a = 1, b = "b", c = 3]

    co[2:d]
    # [b = "b", c = 3, d = "d"]

    co[-(b:c)]
    # [a = 1, d = "d"]

    co[-c("a", "d")]
    # [b = "b", c = 3]

This also works for replacement operations.

    # Replace by NSE name range
    co[a:c] <- 0
    co
    # [a = 0, b = 0, c = 0, d = "d"]

    # Replace complement via negative NSE range
    co[-(a:b)] <- 5:6
    co
    # [a = 0, b = 0, c = 5L, d = 6L]

Warning: range expressions as shown above are truly intended for interactive use, where the result can be easily inspected and corrected by the user. They should not be used in serious programming where explicit indices are preferred to avoid unexpected results.

##### Default values

Invalid indices don’t produce `NULL`s but are just ignored.

    co <- container(a = 1, b = "b", c = 3, d = "d")

    co[0:10]
    # [a = 1, b = "b", c = 3, d = "d"]

    co[1, "foo", "c", "bar"]
    # [a = 1, c = 3]

It is possible to provide a custom default value for unknown indices.

    co[0:10, .default = 0]
    # [a = 1, b = "b", c = 3, d = "d", 0, 0, 0, 0, 0, 0]

    co[1, "foo", "c", "bar", .default = NA]
    # [a = 1, foo = NA, c = 3, bar = NA]

    co[1, "foo", "c", "bar", .default = "ups"]
    # [a = 1, foo = "ups", c = 3, bar = "ups"]

    co[1, "foo", "c", "bar", .default = 1:3]
    # [a = 1, foo = (1L 2L 3L), c = 3, bar = (1L 2L 3L)]

### Element inspection

Count the number of elements.

    co <- container(a = 1, b = "foo", c = 1, d = "foo")
    count(co, 1)
    # [1] 2

    count(co, "foo")
    # [1] 2

## Summary

This vignette showcases how {container} enhances interactive R workflows by combining the familiarity of base R list operations with additional features:

- Compact printing for quick overviews, with options for detailed inspection via as.list() and str().
- Flexible adding and replacing of elements, supporting mixed indices and preventing out-of-bounds additions.
- Intuitive extraction using familiar operators as well as advanced features like mixed indices, non-standard evaluation for range selection, and custom default values for missing elements.

Next, see vignette Use container for code development.