AGPL-3.0-or-later · forever.

the path · 07

for_each fan-out — one task, many items.

run itnika try 07-for-each-locales

07-for-each-locales.nika.yaml
# SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## 07 · for_each fan-out — one task, many items.## 02 fanned out by writing three tasks. That works until the list is decided# at run time, or has fifty entries. `for_each:` is the same fan-out with the# collection as data: one task definition, one iteration per element, and a# `.output` that is the array of results in input order.## Demonstrates ·#   - `for_each:` · run a task once per element of a collection#   - `${{ item }}` + `${{ index }}` · loop-scoped locals, not a namespace#   - `max_parallel:` · a ceiling on concurrent iterations#   - `fail_fast: false` · finish the batch even when one element fails#   - fan-in · the whole array lands in one downstream binding## Run · nika run examples/07-for-each-locales.nika.yamlnika: v1workflow:  id: for-each-localesmodel: mock/echo   # the dry twin · this file teaches the loop, not the translationspermits: {}        # pure compute · no file, no host, no program (see 01)const:  source: "Welcome to the launch."  locales: ["fr", "es", "de", "ja", "pt"]tasks:  translate:    for_each: ${{ const.locales }}   # five elements → five iterations    max_parallel: 3                  # at most 3 in flight · the rest queue    # Default is fail_fast: true — the first failure cancels the siblings.    # A batch job usually wants the opposite: four good translations beat    # zero, and you would rather learn which one broke.    fail_fast: false    on_error:      # Without this, a failed element fails the task even under      # fail_fast: false. `recover: null` keeps the array whole and puts a      # null at that index — so filter nulls at the fan-in below.      recover: null    with:      locale: ${{ item }}   # the current element      n: ${{ index }}       # its 0-based position    infer:      prompt: "Translate to locale '${{ with.locale }}' (#${{ with.n }}) · ${{ const.source }}"      max_tokens: 256  collect:    with:      # One binding, five results. `tasks.translate.output` is the ARRAY, in      # the order of `const.locales` — not the order they finished.      translations: ${{ tasks.translate.output }}    infer:      prompt: "Combine these translations into a localization table · ${{ with.translations }}"      max_tokens: 1024# Both the array and the table, so the ordering guarantee is visible · read# with `--output json`.outputs:  translations: ${{ tasks.translate.output }}  table: ${{ tasks.collect.output }}

nika-spec@6ac29351a · sha256 aaa32bb4b1cc5709