Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
manipulating_tables_and_lookup_tables [2026/07/25 04:12] hermann |
manipulating_tables_and_lookup_tables [2026/07/25 04:29] (current) hermann |
||
|---|---|---|---|
| Line 302: | Line 302: | ||
| A [[Mux Table]] or [[Mux Lookup Table]] can carry a Table or Lookup Table across the iterations of a loop, the same way [[Mux Value]] carries a single value — see [[ego_script#carrying_and_selecting_values_across_iterations|Carrying and selecting values across iterations]]. Each iteration reads the mux's current output, adds a row to it with ''AddTableRow'', and feeds the result back in as the mux's ''feedback'' input for the next iteration, building up a result table one row at a time. | A [[Mux Table]] or [[Mux Lookup Table]] can carry a Table or Lookup Table across the iterations of a loop, the same way [[Mux Value]] carries a single value — see [[ego_script#carrying_and_selecting_values_across_iterations|Carrying and selecting values across iterations]]. Each iteration reads the mux's current output, adds a row to it with ''AddTableRow'', and feeds the result back in as the mux's ''feedback'' input for the next iteration, building up a result table one row at a time. | ||
| - | Neither [[For Each]] nor [[While]]/[[Do While]] has a data output of its own — each only has a sequencing output, per its own entry in the functor catalog. So there's no dedicated port to "collect" the final accumulated table once the loop ends. Instead, a functor placed outside the loop simply references the accumulator's feedback variable directly, the same way any functor can reference a variable produced inside a container; per [[basic_data_flow|Basic Data Flow]], that reference is itself a dependency on the whole loop, so Dinamica waits for every iteration to finish before evaluating it. | + | The accumulated table is read after the loop the same way any container's internal result is read from outside it: a functor after the loop simply takes the accumulator's feedback variable as an input. There's nothing special about this — the loop is guaranteed to finish before anything depending on it runs, per [[basic_data_flow|Basic Data Flow]]. |
| <code> | <code> | ||
| Line 327: | Line 327: | ||
| }}; | }}; | ||
| - | // finalResults holds every row added across every iteration, not just the | + | // finalResults holds every row added across all iterations. Use nextAccumulated, |
| - | // last one — accumulated (the mux's own output) would lag one iteration behind. | + | // not accumulated (the mux's own output), which lags one iteration behind. |
| - | // A bare `finalResults := nextAccumulated;` isn't valid — := always binds the | + | // The Table carrier passes it through, since := always binds a functor call. |
| - | // result of a functor call, never just another variable's name — so the Table | + | |
| - | // carrier functor is used here to re-expose the value under a new binding. | + | |
| finalResults := Table nextAccumulated; | finalResults := Table nextAccumulated; | ||
| </code> | </code> | ||
| + | |||
| + | > **Note:** This is also why ''accumulated'' should never be read again after ''AddTableRow'' consumes it in the same iteration. When exactly one reference to a table's current version remains, Dinamica can update it destructively — modifying the existing storage in place. A second live reference to ''accumulated'' (reading it directly somewhere else, instead of only through ''nextAccumulated'') forces Dinamica to copy the table instead, since the old version now has to stay intact for that other reference. That copy cost repeats every iteration — see [[basic_data_flow|Basic Data Flow]] for this same rule stated generally, beyond just tables. | ||
| **Why this isn't the best approach.** [[basic_data_flow|Basic Data Flow]] documents three conditions under which a loop's iterations can run simultaneously: no mux directly inside the loop, nothing produced inside the loop consumed outside it, and no loop member used as a submodel's output port. A mux-based accumulator like the one above breaks the first condition outright — the mux ties every iteration to the one before it, so the loop can never run as anything but sequential, even when the per-iteration work is otherwise completely independent, as it is above (each row's value depends only on that row's own key). | **Why this isn't the best approach.** [[basic_data_flow|Basic Data Flow]] documents three conditions under which a loop's iterations can run simultaneously: no mux directly inside the loop, nothing produced inside the loop consumed outside it, and no loop member used as a submodel's output port. A mux-based accumulator like the one above breaks the first condition outright — the mux ties every iteration to the one before it, so the loop can never run as anything but sequential, even when the per-iteration work is otherwise completely independent, as it is above (each row's value depends only on that row's own key). | ||