構文
参照

参照

参照は値の再利用を可能にします。繰り返し構造を生み出すこともできます。

複数行のプログラム

インタプリタで複数行の入力を行う際は、 :{:} をあらかじめ入力します。Haskell のインタプリタと同様です。

> :{
> 1 -> output
> 2 -> output
> :}
2
1
2
1.

ファイルからのプログラム読み込み

複数行の入力を毎回インタプリタから行うのは大変です。flow のインタプリタでは、プログラムを書いたファイルを読み込むことができます。flow のファイルの拡張子は .~ が推奨されています。

test.~
1 -> output
2 -> output

:l コマンドを用いてファイルの読み込みができます。この機能はブラウザからは使えないので、ローカルのランタイムで実行してください。

> :l test.~
1
2
1
2.

参照の基本

参照は「トンネル」のような役割を果たすノードです。 @a などとして表現します。

> :{
> 1 -> @a
> @a -> output
> :}
1.

参照は複数の下流にデータを流すことができます。その場合、参照は copy のような役割を果たし、上流からのデータをすべての下流に流します。

> :{
> 1 -> @a
> @a + @a -> output
> :}
2.

参照は複数の上流からは受け取れない

参照は複数の下流を持つことができる一方で、複数の上流は持つことができません。どこからでも参照にデータを流すことを許すと、コードが読みにくくなり、バグの温床になってしまうからです。

参考: 参照は Verilog でいう wire に似ていますが、Verilog のコードを回路に合成する際にも wire が複数回 assign されていると multi-driven だといわれることがあります。これは電気的な制約によるものですが、制限されていることは同じです。

> :{
> 1 -> @a
> 2 -> @a
> :}
The ref a is multi-driven.

もし複数の入力を用いたければ、 merge ノードを用いることをお勧めします。このノードは、複数の上流と 1 つの下流を持ち、上流から来たデータを下流に流します。

> :{
> (1 ->) (2 ->) merge -> @a
> @a -> output
> :}
1
2
1
2.

参照でループを作る

次のようなプログラムを実行すると、数字が加算されながら流れ続けます。

> @a'0 -> trace -> + 1 -> @a
0
1
2
3
4
5
6.

いくつか新しい構文が出てきたので、説明します。

@a の後についている '0 は、最初に下流に流すデータを指定しています。これがないと、このプログラムには何も流れなくなってしまいます。

trace は、 output と似ていますが、出力をしつつ上流から来たデータを下流に流します。 trace を使わずに、次のように書くこともできます。

> @a'0 -> copy (-> output) (-> + 1 -> @a)

実践: 階乗を計算する

繰り返しを用いることで、再帰的な関数を書くことができます!試しに階乗を計算してみましょう。

実装には、「2 つの上流を持つ if 」を利用します。これは、片方の上流(名前: condition)が条件となり、もう片方の上流(名前: value)が下流(then か else)に流すデータを定めます。then だけを見ると、条件と合わせてトランジスタのように働きます。

> (2 ->:value) (1 == 1 ->:condition) if (then:-> output) (else:-> * 2 -> output)
2.

次のプログラムは階乗( @x で指定された数の階乗)を計算します。糖衣構文を多用していますが、糖衣構文については後の章で説明します。

> :{
> 5 -> @x
> @next'1 * @current'1 -> @result
> @result -> if (@current'1 == @x) (then:-> output) (else:-> @next)
> @current'1 + 1 -> @current
> :}
120.

糖衣構文を用いなければ次のものと等価です。

> :{
> 5 -> @x
> (@next'1 ->) (@current'1 ->) * -> @result
> ((@current'1 ->) (@x ->) == ->:condition) (@result ->:value) if (then:-> output) (else:-> @next)
> (@current'1 ->) (1 ->) + -> @current
> :}
120.