---
title: "Introduction to container"
output:
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 4
description: >
  Start here if this is your first time using container. This vignette
  describes when and when not to use container, and gives a brief introduction
  on basic container operations.
vignette: >
  %\VignetteIndexEntry{Introduction to container}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r knitr-setup, include = FALSE}
unloadNamespace("dplyr")
require(container)
has = container::has
has_name = container::has_name


knitr::opts_chunk$set(
  comment = "#",
  prompt = F,
  tidy = FALSE,
  cache = FALSE,
  collapse = T
)

old <- options(width = 100L)
```


## 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](https://CRAN.R-project.org/package=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](https://CRAN.R-project.org/package=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](code-development.html)
* feature rich [specialized data structures](deque-set-dict.html) beyond lists
* lists with [reference semantics](reference-semantics.html).

Furthermore consider using `dict.table` for a flexible and robust way to
[manage data columns](manage-data-columns.html) 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`.

```{r}
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.
```{r}
print(co)
```

For more verbose output, either convert to a base `list` ...
```{r}
as.list(co)
```

or use `str`.
```{r}
str(co)
```

Both `length` and `names` work as usual.
```{r}
length(co)

names(co)

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

A container can also be constructed from a list.
```{r}
l = list(x = (1:2)^1, y = (1:2)^2)
co2 = as.container(l)
co2
```


### Add elements

Elements can be added by concatenation,
```{r}
c(co, co2)
```
or name,
```{r}
co[["c"]] <- 3
co
```

and containers can be nested.
```{r}
co[["co2"]] <- co2
co
```

In contrast to base R `list`, elements cannot be added via positional index
if it exceeds the container's length.
```{r, error = TRUE}
co[[5]] <- 5
```


### Replace values

Single or multiple value replacement works as usual.
```{r}
co[[3]] <- 0
co[1:2] <- 0
co
```

In contrast to base `list`, containers can take a mix of numeric and character
indices.
```{r}
co[list("A", 2, "c")] <- list(1, 2, "three")
co
```

Another option for container object is to replace *by value*.
```{r}
co[[{"three"}]] <- 3
co
```

This works for any data type.
```{r}
co[[{co2}]] <- 3
co
```


### Extract
The standard operators to access elements also should be familiar to R users.
^[Note that the `$` operator does not work.]
```{r}
co[[1]]
co[1:3]
```

As another option, you can pass any number of indices, possibly mixed as numeric
and character.
```{r}
co[1, 3, "b"]

co[2:1, "A"]
```

Invalid indices don't produce `NULL`s but are just ignored.
```{r}
co[1:100]
```


### Inspect
Count the number of elements.
```{r}
count(co, 1)
count(co, 3)
```


Use the apply family.
```{r}
sapply(co, is.numeric)

sapply(co, function(x) x + 1)
```

## container in code development

Next, see vignette [Container operations for robust code](code-development.html).

```{r, include = FALSE}
options(old)
```