# Resources in Arrays and Dictionaries

Arrays and dictionaries behave differently when they contain resources: It is **not** allowed to index into an array to read an element at a certain index or assign to it, or index into a dictionary to read a value for a certain key or set a value for the key.

Instead, use a swap statement (`<->`) or shift statement (`<- target <-`) to replace the accessed resource with another resource.

```
resource R {}

// Declare a constant for an array of resources.
// Create two resources and move them into the array.
//
let resources <- [
    <-create R(),
    <-create R()
]

// Invalid: Reading an element from a resource array is not allowed.
//
let firstResource <- resources[0]

// Invalid: Setting an element in a resource array is not allowed,
// as it would result in the loss of the current value.
//
resources[0] <- create R()

// Instead, when attempting to either read an element or update an element
// in a resource array, use a swap statement with a variable to replace
// the accessed element.
//
var res <- create R()
resources[0] <-> res
// `resources[0]` now contains the new resource.
// `res` now contains the old resource.

// Use the shift statement to move the new resource into
// the array at the same time that the old resource is being moved out
let oldRes <- resources[0] <- create R()
// The old object still needs to be handled
destroy oldRes
```

The same applies to dictionaries.

```
// Declare a constant for a dictionary of resources.
// Create two resources and move them into the dictionary.
//
let resources <- {
    "r1": <-create R(),
    "r2": <-create R()
}

// Invalid: Reading an element from a resource dictionary is not allowed.
// It's not obvious that an access like this would have to remove
// the key from the dictionary.
//
let firstResource <- resources["r1"]

// Instead, make the removal explicit by using the `remove` function.
let firstResource <- resources.remove(key: "r1")

// Invalid: Setting an element in a resource dictionary is not allowed,
// as it would result in the loss of the current value.
//
resources["r1"] <- create R()

// Instead, when attempting to either read an element or update an element
// in a resource dictionary, use a swap statement with a variable to replace
// the accessed element.
//
var res <- create R()
resources["r1"] <-> res
// `resources["r1"]` now contains the new resource.
// `res` now contains the old resource.

// Use the shift statement to move the new resource into
// the dictionary at the same time that the old resource is being moved out
let oldRes <- resources["r2"] <- create R()
// The old object still needs to be handled
destroy oldRes
```

Resources cannot be moved into arrays and dictionaries multiple times, as that would cause a duplication.

```
let resource <- create R()

// Invalid: The resource variable `resource` can only be moved into the array once.
//
let resources <- [
    <-resource,
    <-resource
]
```

```
let resource <- create R()

// Invalid: The resource variable `resource` can only be moved into the dictionary once.
let resources <- {
    "res1": <-resource,
    "res2": <-resource
}
```

Resource arrays and dictionaries can be destroyed.

```
let resources <- [
    <-create R(),
    <-create R()
]
destroy resources
```

```
let resources <- {
    "r1": <-create R(),
    "r2": <-create R()
}
destroy resources
```

The variable array functions like `append`, `insert`, and `remove` behave like for non-resource arrays. Note however, that the result of the `remove` functions must be used.

```
let resources <- [<-create R()]
// `resources.length` is `1`

resources.append(<-create R())
// `resources.length` is `2`

let first <- resource.remove(at: 0)
// `resources.length` is `1`
destroy first

resources.insert(at: 0, <-create R())
// `resources.length` is `2`

// Invalid: The statement ignores the result of the call to `remove`,
// which would result in a loss.
resource.remove(at: 0)

destroy resources
```

The variable array function `contains` is not available, as it is impossible: If the resource can be passed to the `contains` function, it is by definition not in the array.

The variable array function `concat` is not available, as it would result in the duplication of resources.

The dictionary functions like `insert` and `remove` behave like for non-resource dictionaries. Note however, that the result of these functions must be used.

```
let resources <- {"r1": <-create R()}
// `resources.length` is `1`

let first <- resource.remove(key: "r1")
// `resources.length` is `0`
destroy first

let old <- resources.insert(key: "r1", <-create R())
// `old` is nil, as there was no value for the key "r1"
// `resources.length` is `1`

let old2 <- resources.insert(key: "r1", <-create R())
// `old2` is the old value for the key "r1"
// `resources.length` is `2`

destroy old
destroy old2
destroy resources
```
