A _`for` expression_ creates a complex type value by transforming
another complex type value. Each element in the input value
can correspond to either one or zero values in the result, and an arbitrary
expression can be used to transform each input element into an output element.
For example, if `var.list` is a list of strings, then the following expression
produces a list of strings with all-uppercase letters:
```hcl
[for s in var.list : upper(s)]
```
This `for` expression iterates over each element of `var.list`, and then
evaluates the expression `upper(s)` with `s` set to each respective element.
It then builds a new tuple value with all of the results of executing that
expression in the same order.
The type of brackets around the `for` expression decide what type of result
it produces. The above example uses `[` and `]`, which produces a tuple. If
`{` and `}` are used instead, the result is an object, and two result
expressions must be provided separated by the `=>` symbol:
```hcl
{for s in var.list : s => upper(s)}
```
This expression produces an object whose attributes are the original elements
from `var.list` and their corresponding values are the uppercase versions.
A `for` expression can also include an optional `if` clause to filter elements
from the source collection, which can produce a value with fewer elements than
the source:
```text
[for s in var.list : upper(s) if s != ""]
```
The source value can also be an object or map value, in which case two
temporary variable names can be provided to access the keys and values
respectively:
```text
[for k, v in var.map : length(k) + length(v)]
```
Finally, if the result type is an object (using `{` and `}` delimiters) then
the value result expression can be followed by the `...` symbol to group
together results that have a common key:
```text
{for s in var.list : substr(s, 0, 1) => s... if s != ""}
```
<!---
## TODO: revamp this section
## Splat Expressions
A _splat expression_ provides a more concise way to express a common operation
that could otherwise be performed with a `for` expression.
If `var.list` is a list of objects that all have an attribute `id`, then a list
of the ids could be produced with the following `for` expression:
```hcl
[for o in var.list : o.id]
```
This is equivalent to the following _splat expression:_
```hcl
var.list[*].id
```
The special `[*]` symbol iterates over all of the elements of the list given to
its left and accesses from each one the attribute name given on its right. A
splat expression can also be used to access attributes and indexes from lists
of complex types by extending the sequence of operations to the right of the
symbol:
```hcl
var.list[*].interfaces[0].name
```
The above expression is equivalent to the following `for` expression:
```hcl
[for o in var.list : o.interfaces[0].name]
```
Splat expressions are for lists only (and thus cannot be used [to reference
resources created with
`for_each`](https://www.terraform.io/docs/configuration/resources.html#referring-to-instances), which
are represented as maps). However, if a splat expression is applied to a value
that is _not_ a list or tuple then the value is automatically wrapped in a
single-element list before processing.
For example, `var.single_object[*].id` is equivalent to
`[var.single_object][*].id`, or effectively `[var.single_object.id]`. This
behavior is not interesting in most cases, but it is particularly useful when
referring to resources that may or may not have `count` set, and thus may or
may not produce a tuple value:
```hcl
aws_instance.example[*].id
```
The above will produce a list of ids whether `aws_instance.example` has `count`
set or not, avoiding the need to revise various other expressions in the
configuration when a particular resource switches to and from having `count`
set.
--->
## `dynamic` blocks
Within top-level block constructs like sources, expressions can usually be used
only when assigning a value to an argument using the `name = expression` or `key = expression` form. This covers many uses, but some source types include
repeatable _nested blocks_ in their arguments, which do not accept expressions:
```hcl
service {
port = "db" # can use expressions here
check {
# but the "check" block is always a literal block
}
}
```
You can dynamically construct repeatable nested blocks like `check` using a
special `dynamic` block type, which is supported anywhere, example: