Intermediate
When you need to apply an operation to every element of a list, you could write a loop — but Phograph offers a more declarative approach. List annotations tell the runtime to automatically map a node over a list of inputs.
The ListMap annotation marks a node so that it runs once per
element of its list input. The results are collected into a new list.
constant [1, 2, 3, 4] --> [* (ListMap)] <-- constant 10
outputs: [10, 20, 30, 40]
Here the * node is annotated with ListMap. The left input is a
list, so the node fires four times — once per element — multiplying
each by 10.
When one input is a list and another is a scalar (single value), the scalar
is broadcast — reused for every element. In the example
above, 10 is a scalar and is paired with each element of the list.
constant ["a","b","c"] --> [concat (ListMap)] <-- constant "-suffix"
outputs: ["a-suffix", "b-suffix", "c-suffix"]
The Partition annotation splits a list into two lists based on
a boolean predicate. Elements for which the predicate returns true go into
the first output; the rest go into the second.
constant [1,2,3,4,5,6] --> [is-even? (Partition)]
output 1 (true): [2, 4, 6]
output 2 (false): [1, 3, 5]
List annotations and loops can accomplish similar tasks, but they have different strengths:
Loop version of the multiply example:
constant [1,2,3,4] --> [loop: map-times-10]
shift register "result" starts at []
body: element * 10 --> append to result
output: [10, 20, 30, 40]
ListMap version (much simpler):
constant [1,2,3,4] --> [* (ListMap)] <-- constant 10
output: [10, 20, 30, 40]