# Introduction to container

## When not to use container

Don’t bother using the `container` framework if speed is of high importance. An exception is the `dict.table` class, which is very fast as it is based on data.table. Other than that, if computation speed is critical for your application, we refer you to using base R list or packages that were optimized for performance, such as the collections package.

## When to use container

Consider using the `container` framework over base `list` if you are looking for …

- feature-rich and safe access, replace, and remove operations for robust code
- feature rich specialized data structures beyond lists
- lists with reference semantics.

Furthermore consider using `dict.table` for a flexible and robust way to manage data columns of `data.table`s.

## container in interactive R session

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 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

Elements can be added by concatenation,

    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 values

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)]]

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 for container object 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}]] <- 3
    co
    # [A = 1, b = 2, c = 3, co2 = 3]

### Extract

The standard operators to access elements also should be familiar to R users. 1

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

As another option, you can pass any number of indices, possibly mixed as numeric and character.

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

    co[2:1, "A"]
    # [b = 2, A = 1, A = 1]

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

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

### Inspect

Count the number of elements.

    count(co, 1)
    # [1] 1
    count(co, 3)
    # [1] 2

Use the apply family.

    sapply(co, is.numeric)
    #    A    b    c  co2
    # TRUE TRUE TRUE TRUE

    sapply(co, function(x) x + 1)
    #   A   b   c co2
    #   2   3   4   4

## container in code development

Next, see vignette Container operations for robust code.

1. Note that the `$` operator does not work.↩︎