Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision | |||
|
basic_data_flow [2026/07/29 21:11] hermann |
basic_data_flow [2026/07/30 19:19] (current) hermann |
||
|---|---|---|---|
| Line 11: | Line 11: | ||
| In [[ego_script|EGO Script]], a connection is expressed by giving an output a variable name and reusing that same name as an input elsewhere — see [[ego_script#functors_variables_and_binding|Functors, variables, and binding]]. In the GUI, the same connection is drawn as a wire between two functor boxes. Either way, what the engine sees is a connection between two ports; the variable name or the wire is only how that connection happens to be written down. | In [[ego_script|EGO Script]], a connection is expressed by giving an output a variable name and reusing that same name as an input elsewhere — see [[ego_script#functors_variables_and_binding|Functors, variables, and binding]]. In the GUI, the same connection is drawn as a wire between two functor boxes. Either way, what the engine sees is a connection between two ports; the variable name or the wire is only how that connection happens to be written down. | ||
| - | A connection doesn't require its two ports to share exactly the same type. When the types are compatible, the value is converted automatically as part of crossing the connection — a Real value connected to a port expecting a Tuple becomes a one-element Tuple, for instance. This conversion is a property of the connection itself, not of the value: the same value, written directly into that port as a literal constant instead of connected to it, is not converted at all — a constant is parsed by its target port's own type-specific parser, which recognizes only that one type's literal syntax and rejects every other form, however closely related the types might otherwise be. See [[ego_script#constants|Constants]] for how this distinction is expressed in EGO Script specifically. | + | A connection doesn't require its two ports to share exactly the same type. When the types are compatible, the value is converted automatically as part of crossing the connection — a Real value connected to a port expecting a Tuple becomes a one-element Tuple, for instance. This conversion is a property of the connection itself, not of the value: the same value, written directly into that port as a literal constant instead of connected to it, is not converted at all — a constant is parsed by its target port's own type-specific parser, which recognizes only that one type's literal syntax and rejects every other form, however closely related the types might otherwise be. See [[ego_script#constants|Constants]] for how this distinction is expressed in EGO Script specifically, and [[type_system|Type System]] for the complete catalog of types and their conversions. |
| ===== Data dependencies drive execution order ===== | ===== Data dependencies drive execution order ===== | ||
| Line 33: | Line 33: | ||
| ===== Ordering without data: sequence connections ===== | ===== Ordering without data: sequence connections ===== | ||
| - | Sometimes two functors, or two containers, need to run in a specific order even though neither produces a value the other needs. For this, some functors expose sequencing-only ports that carry no data of their own — a connection between them exists purely to force an order. This is the same graph mechanism as an ordinary connection; it simply carries nothing. See [[ego_script#sequence_ports|Sequence ports]] for the EGO Script syntax. | + | Sometimes two functors, or two containers, need to run in a specific order even though neither produces a value the other needs. For this, some functors expose sequencing-only ports that carry no data of their own — a connection between them exists purely to force an order. This is the same graph mechanism as an ordinary connection; it simply carries nothing, which is possible because almost every type in the system converts automatically to the type these ports share — see [[type_system#sequencing|Type System]] for that conversion listed against every type it applies to. See [[ego_script#sequence_ports|Sequence ports]] for the EGO Script syntax. |
| ===== The one exception: feedback in loops ===== | ===== The one exception: feedback in loops ===== | ||
| Line 50: | Line 50: | ||
| This has a particular consequence for mux-fed loops. A value that a functor inside the loop destructively updates on every iteration, and that something outside the loop also reads, can never benefit from the read-before-update scheduling above. The outside reference, per the container rule, can only run once the entire loop has finished — so it can never be scheduled ahead of any single iteration's update, on any pass. Since every iteration executes the same loop body, the engine cannot tell in advance which pass is the last one that outside reference actually needs; it copies the value on every iteration instead, just to keep it safe for that pending read. Feeding the outside reference from the value produced //after// each iteration's update, rather than the mux's own output, avoids creating this conflict at all: nothing destructively updates that value again once it's produced, so there is nothing for the outside reference to wait behind. | This has a particular consequence for mux-fed loops. A value that a functor inside the loop destructively updates on every iteration, and that something outside the loop also reads, can never benefit from the read-before-update scheduling above. The outside reference, per the container rule, can only run once the entire loop has finished — so it can never be scheduled ahead of any single iteration's update, on any pass. Since every iteration executes the same loop body, the engine cannot tell in advance which pass is the last one that outside reference actually needs; it copies the value on every iteration instead, just to keep it safe for that pending read. Feeding the outside reference from the value produced //after// each iteration's update, rather than the mux's own output, avoids creating this conflict at all: nothing destructively updates that value again once it's produced, so there is nothing for the outside reference to wait behind. | ||
| - | |||
| - | |||