References
References allow you to reuse values and can be used to create loops.
Multi-line Programs
When entering multi-line input in the interpreter, use :{ and :}. This is similar to Haskell's interpreter.
> :{
> 1 -> output
> 2 -> output
> :}
2
1
2
1.Loading Programs from Files
Typing multiple lines in the interpreter repeatedly is sometimes troublesome. Flow allows loading programs from a file. Flow files are recommended to have the extension .~.
1 -> output
2 -> outputYou can load the file using the :l command. This feature cannot be used in the browser; use a local runtime instead.
> :l test.~
1
2
1
2.Basics of References
A reference acts like a "tunnel" node and is expressed as @ + name.
> :{
> 1 -> @a
> @a -> output
> :}
1.References can send data to multiple downstream nodes. In this case, a reference acts like copy, sending upstream data to all downstream nodes.
> :{
> 1 -> @a
> @a + @a -> output
> :}
2.References Cannot Have Multiple Upstreams
While references can have multiple downstream nodes, they cannot have multiple upstream nodes.
Note: This is similar to a wire in HDL. When synthesizing HDL such as Verilog, a wire assigned multiple times is called multi-driven, which is restricted for electrical reasons.
> :{
> 1 -> @a
> 2 -> @a
> :}
The ref a is multi-driven.If you need multiple inputs, use a merge node. It has multiple upstream nodes and one downstream, sending all upstream data downstream.
> :{
> (1 ->) (2 ->) merge -> @a
> @a -> output
> :}
1
2
1
2.Creating Loops with References
The following program continuously flows numbers while incrementing them:
> @a'0 -> trace -> + 1 -> @a
0
1
2
3
4
5
6.Some new syntax appears here:
- The
'0after@aspecifies the initial data to send downstream. Without it, nothing would flow. traceis similar tooutputbut passes the upstream data downstream while displaying it. You could also write:
> @a'0 -> copy (-> output) (-> + 1 -> @a)Practical Example: Calculating Factorial
Using loops, you can write recursive functions! Let's calculate a factorial.
We use an if node with two upstreams: one (condition) determines the condition, and the other (value) provides the data to send downstream (then or else). The then part works like a transistor with the condition.
> (2 ->:value) (1 == 1 ->:condition) if (then:-> output) (else:-> * 2 -> output)
2.The following program calculates the factorial of a number specified by @x. It uses syntactic sugar extensively (explained in later chapters):
> :{
> 5 -> @x
> @next'1 * @current'1 -> @result
> @result -> if (@current'1 == @x) (then:-> output) (else:-> @next)
> @current'1 + 1 -> @current
> :}
120.Without syntactic sugar, this is equivalent to:
> :{
> 5 -> @x
> (@next'1 ->) (@current'1 ->) * -> @result
> ((@current'1 ->) (@x ->) == ->:condition) (@result ->:value) if (then:-> output) (else:-> @next)
> (@current'1 ->) (1 ->) + -> @current
> :}
120.