For each: loop over a list and stop at the first match #249

Closed
opened 2026-09-27 17:41:31 +02:00 by meleki · 1 comment
Owner

A loop over a list that can stop at the first element a condition holds for — the graph's list.FirstOrDefault(x => …).

Today finding an element by one of its fields takes Count → Repeat → Item at → Expand → Equals → Branch, and the loop runs to the end even after the match.

Node For each (flow, next to Repeat)

Inputs

  • exec
  • list
  • break (boolean, default false)

Outputs

  • body (exec): runs once per element
  • item: the element of the round
  • index: its position
  • stopped (boolean): whether break ended the loop
  • done (exec): after the loop

Rules

  • break is read anew before every round, after item and index are set. So a condition built on item (e.g. Expand(item).Name == "Test") asks about the element at hand. This is the predicate.
  • Once break is true, the loop ends there: that round's body does not run, and done sees that round's item and index with stopped = true.
  • Without a break, done sees no item, index -1 and stopped false (the "OrDefault").
  • An empty list goes straight to done.
  • Every round reads its data inputs anew, like Repeat, so a variable the body changes is seen by the next round's break.
A loop over a list that can stop at the first element a condition holds for — the graph's `list.FirstOrDefault(x => …)`. Today finding an element by one of its fields takes `Count` → `Repeat` → `Item at` → `Expand` → `Equals` → `Branch`, and the loop runs to the end even after the match. ## Node `For each` (flow, next to `Repeat`) **Inputs** - `exec` - `list` - `break` (boolean, default false) **Outputs** - `body` (exec): runs once per element - `item`: the element of the round - `index`: its position - `stopped` (boolean): whether `break` ended the loop - `done` (exec): after the loop **Rules** - `break` is read anew **before every round**, after `item` and `index` are set. So a condition built on `item` (e.g. `Expand(item).Name == "Test"`) asks about the element at hand. This is the predicate. - Once `break` is true, the loop ends there: that round's `body` does not run, and `done` sees that round's `item` and `index` with `stopped` = true. - Without a break, `done` sees no item, `index` -1 and `stopped` false (the "OrDefault"). - An empty list goes straight to `done`. - Every round reads its data inputs anew, like `Repeat`, so a variable the body changes is seen by the next round's `break`.
Author
Owner

Done in cb8a2d0.

  • For each (flow): inputs exec, list, break; outputs body, item, index, stopped, done.
  • break is read anew before every round, after item and index are set. Once it is true the loop ends there: that round's body does not run, done sees the match with stopped true.
  • Without a match done sees no item, index -1 and stopped false (the "OrDefault").
  • FirstOrDefault(x => x.Name == "Gold"): item → Expand (Name) → Equals "Gold" → break, and a Branch on stopped after done.
  • Like Repeat, every round reads its data inputs anew, so a variable the body changes counts for the next round's break.

Tests: gate 2623 tests green, e2e 1-6 269 checks (new 6z-iv, 2 checks). Counter-checks: without the break check 2 unit tests fail, with break not read over its edge 6z-iv fails.

Wiki: Behaviors.

Done in cb8a2d0. - **For each** (flow): inputs `exec`, `list`, `break`; outputs `body`, `item`, `index`, `stopped`, `done`. - `break` is read anew before every round, after `item` and `index` are set. Once it is true the loop ends there: that round's `body` does not run, `done` sees the match with `stopped` true. - Without a match `done` sees no item, `index` -1 and `stopped` false (the "OrDefault"). - `FirstOrDefault(x => x.Name == "Gold")`: `item` → `Expand` (Name) → `Equals "Gold"` → `break`, and a `Branch` on `stopped` after `done`. - Like `Repeat`, every round reads its data inputs anew, so a variable the body changes counts for the next round's break. Tests: gate 2623 tests green, e2e 1-6 269 checks (new 6z-iv, 2 checks). Counter-checks: without the break check 2 unit tests fail, with `break` not read over its edge 6z-iv fails. Wiki: [Behaviors](https://git.nockal.com/meleki/game-maker/wiki/Behaviors).
admin added this to the Development project 2026-09-27 22:17:06 +02:00
admin moved this to Done in Development on 2026-09-27 22:17:39 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#249