---
title: "Use container in interactive session"
output:
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 4
description: >
  A starting point for new users, this vignette introduces the basic functionality
  of {container}. It provides guidance on when to use the package, explains key operations, and illustrates how {container} improves upon base R lists.
vignette: >
  %\VignetteIndexEntry{Use container in interactive session}
  %\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 = FALSE,
  tidy = FALSE,
  cache = FALSE,
  collapse = TRUE
)

old <- options(width = 100L)
```


## 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`.

```{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} object 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 can be added by concatenation,

```{r}
c(co, c = 3, d = 4)

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

Single or multiple value replacement works as usual.

```{r}
co[[3]] <- 0
co[1:2] <- 0

co
```

Note that assigning `NULL` does *not* remove the element, but just replaces its value with `NULL`.

```{r}
co[["A"]] <- NULL

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 is to replace *by value*.

```{r}
co[[{"three"}]] <- 3

co
```

This works for any data type.

```{r}
co[[{co2}]] <- 4

co
```


### Extract

#### Basic extraction

The following standard access operators as known from base R can be applied.

```{r}
co <- container(a = 1, b = "b", c = 3, d = "d")
co[["a"]]

co[[1]]

co[1:3]
```


Negative indices (since version 1.1.0) also work as expected.

```{r}
co[-1]

co[-(1:3)]
```

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.

```{r}
co$a

li <- as.list(co)
li$a
```


#### 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()`.

```{r}
co[1, 3, 4]

co[TRUE, FALSE]

co["c", "b", "a"]
```

Second, indices can be mixed, in a list or, again, as separate arguments.

```{r}
co[list(1, "b", 4)]

co[1, "b", 4]
```


##### 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.

```{r}
co[a:c]

co[2:d]

co[-(b:c)]

co[-c("a", "d")]
```

This also works for replacement operations.

```{r}
# Replace by NSE name range
co[a:c] <- 0
co

# Replace complement via negative NSE range
co[-(a:b)] <- 5:6
co
```

**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.

```{r}
co <- container(a = 1, b = "b", c = 3, d = "d")

co[0:10]

co[1, "foo", "c", "bar"]
```

It is possible to provide a custom default value for unknown indices.

```{r}
co[0:10, .default = 0]

co[1, "foo", "c", "bar", .default = NA]

co[1, "foo", "c", "bar", .default = "ups"]

co[1, "foo", "c", "bar", .default = 1:3]
```

### Element inspection

Count the number of elements.

```{r}
co <- container(a = 1, b = "foo", c = 1, d = "foo")
count(co, 1)

count(co, "foo")
```


## 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](v02-code-development.html).

```{r, include = FALSE}
options(old)
```
