> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# for Expressions

> Explains Terraform for expressions for transforming collections into lists, sets, or maps to prepare inputs for for_each and resources with examples and best practices.

For expressions in Terraform are a data-transformation feature, distinct from `count` and `for_each`. While `count` and `for_each` control how many resources Terraform creates, for expressions are used to reshape or derive new data structures (lists, sets, maps, strings) from existing inputs. Think of them as a preprocessing step: transform the input data with a for expression, then feed the result into `for_each`, module inputs, or other resource arguments.

Below is a compact example followed by a step‑by‑step explanation.

```hcl theme={null}
variable "environments" {
  type    = list(string)
  default = ["prod", "dev", "test"]
}

locals {
  # For expression: transform a list of environment names into resource group names
  resource_group_names = [for env in var.environments : "rg-${env}"]
}

resource "azurerm_resource_group" "rg" {
  # for_each expects a set or map; convert the list into a set to ensure uniqueness and stable keys
  for_each = toset(local.resource_group_names)

  # each.value represents the current element from the collection (here, the resource group name)
  name     = each.value
  location = "eastus"
}
```

<Callout icon="lightbulb" color="#1CB2FE">
  For expressions only produce data—they do not create resources. Use them to prepare or reshape values (lists, sets, maps, strings) that you then pass into `for_each`, resource arguments, modules, or other expressions. They keep configurations DRY and easier to maintain.
</Callout>

Line-by-line explanation

* variable block
  * `variable "environments"` defines a simple list: `["prod", "dev", "test"]`. These are input values only; no resources are created here.
* locals block and the for expression
  * `resource_group_names = [for env in var.environments : "rg-${env}"]`
  * This iterates each element in `var.environments`, transforms the value by prefixing `rg-`, and produces a new list: `["rg-prod", "rg-dev", "rg-test"]`.
* resource block and `for_each`
  * `for_each = toset(local.resource_group_names)` converts the list into a set. `for_each` requires either a set or a map (not a plain list). Converting to a set ensures uniqueness and establishes stable keys that Terraform uses to track resources between runs.
  * Inside the resource block, `each.value` represents the current element from the collection (here, the resource group name) and is used as the `name`.

Why choose a for expression?

* DRY configuration: Add or remove environment names in a single place and derived values update automatically.
* Flexible transformations: Build formatted names, filter elements, or generate complex maps used later in resources or modules.
* Separation of concerns: Locals act as a preprocessing layer—shape inputs exactly the way resources expect them.

Best practices and behavior notes

* For expressions return a collection type (list, set, or map) depending on the syntax and context; they do not create resources.
* Use `toset()` or `tomap()` when required by consumers like `for_each` so Terraform can use stable keys to track resources across runs.
* When using a map with `for_each`, the map keys become resource instance keys and `each.value` is the corresponding value. For sets of primitive values, the element itself becomes the stable identifier used by `for_each`.

<Callout icon="warning" color="#FF6B6B">
  Do not pass a plain list directly into `for_each`. Always convert lists into `toset()` or build a map to ensure deterministic resource keys and avoid unexpected resource recreation.
</Callout>

Quick reference table

| Topic                                            | When to use                                      | Example / Note                                                  |
| ------------------------------------------------ | ------------------------------------------------ | --------------------------------------------------------------- |
| Transform a list of strings into formatted names | When you need consistent naming across resources | Use a for expression in `locals` then `toset()` for `for_each`  |
| Filter elements                                  | Exclude items before resource creation           | `[for e in var.list : e if startswith(e,"prod")]`               |
| Build maps for complex resources                 | When resources need keyed inputs                 | Use `[for k, v in var.map : k => v]` or `merge()` patterns      |
| Ensure stable keys for `for_each`                | Always when creating resources from collections  | Convert list → `toset()` or produce a map with predictable keys |

When to use for expressions

* Any time you need to prepare or transform input data before passing it into `for_each`, module inputs, or resource arguments.
* Useful for consistent naming, filtering unwanted elements, or composing more complex structures from simple variables.

Summary

* For expressions transform data structures—they do not create resources.
* Locals commonly host for expressions to prepare data for resource creation.
* `for_each` consumes transformed data (often after conversion to a set or map), and resources are created based on those values.

Links and references

* [Terraform documentation: For expressions](https://www.terraform.io/docs/language/expressions/for.html)
* [Terraform documentation: for\_each meta-argument](https://www.terraform.io/docs/language/meta-arguments/for_each.html)
* [Terraform locals documentation](https://www.terraform.io/docs/language/values/locals.html)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/terraform-on-azure/module/fb5019bb-df21-4583-818e-6dae40fde2ec/lesson/94612c9a-84fb-4096-bdac-b5765470e478" />
</CardGroup>
