第14章. 多頭関数とガード
この章の目的
この章を読み終える頃には、関数を複数の「頭部」に分けて、各頭部が別のケースを担当するように書けるようになります。この章を読み終える頃には、関数を複数の「頭部」に分けて、各頭部が別のケースを担当するように書けるようになります。
キューごとに準備された応答
演奏者は、指揮者が出すかもしれないキューごとに、別々の応答をリハーサルします。応答は一つのもつれた指示としてではなく、キューごとに分けて書かれます。Keleusmaも関数を同じように書けます。一つの関数名にいくつかの頭部を持たせて、それぞれに独自のケースを与え、関数が呼ばれたときに正しい頭部が選ばれるようにできます。演奏者は、指揮者が出すかもしれないキューごとに、別々の応答をリハーサルします。応答は一つのもつれた指示としてではなく、キューごとに分けて書かれます。Keleusmaも関数を同じように書けます。一つの関数名にいくつかの頭部を持たせて、それぞれに独自のケースを与え、関数が呼ばれたときに正しい頭部が選ばれるようにできます。
値に当てはまる頭部
これはギターの一番細い弦(ハイE弦)のあるフレットのMIDIナンバーを返す関数です。開放弦(0フレット)は独立したケースとして扱っています。これはギターの一番細い弦(ハイE弦)のあるフレットのMIDIナンバーを返す関数です。開放弦(0フレット)は独立したケースとして扱っています。
fn fret_note(0) -> Word { 64 }
fn fret_note(n: Word) -> Word { 64 + n }
fn main() -> Word {
fret_note(5)
}
keleusma runで実行します。出力は69です。
fret_noteには2つの頭部があります。最初の頭部はちょうど0という引数だけに当てはまります。2番目の頭部は束縛nを使い、どの引数にも当てはまります。頭部は書かれた順に試され、最初に当てはまったものが使われます。呼び出しfret_note(5)は0に当てはまらないので、2番目の頭部に進み、64 + 5、つまり69(A4のMIDIナンバー)を返します。fret_noteには2つの頭部があります。最初の頭部はちょうど0という引数だけに当てはまります。2番目の頭部は束縛nを使い、どの引数にも当てはまります。頭部は書かれた順に試され、最初に当てはまったものが使われます。呼び出しfret_note(5)は0に当てはまらないので、2番目の頭部に進み、64 + 5、つまり69(A4のMIDIナンバー)を返します。
順序が大切です。具体的なケース0は、一般的なケースnより前に書きます。逆に書いてしまうと、一般的な頭部があらゆる呼び出しを受け取ってしまい、0の頭部にはたどり着けません。順序が大切です。具体的なケース0は、一般的なケースnより前に書きます。逆に書いてしまうと、一般的な頭部があらゆる呼び出しを受け取ってしまい、0の頭部にはたどり着けません。
ガード付きの頭部
頭部は代わりにwhenガードを持つこともできます。これは第13章のmatchアームに付いていたガードと同じものです。ガードがtrueのときだけ、その頭部が使われます。頭部は代わりにwhenガードを持つこともできます。これは第13章のmatchアームに付いていたガードと同じものです。ガードがtrueのときだけ、その頭部が使われます。
fn tempo_class(bpm: Word) -> Word when bpm < 60 { 0 }
fn tempo_class(bpm: Word) -> Word when bpm < 120 { 1 }
fn tempo_class(bpm: Word) -> Word { 2 }
fn main() -> Word {
tempo_class(90)
}
実行します。出力は1です。tempo_class(90)は最初の頭部を試し、ガード90 < 60がfalseなので、2番目に進みます。そのガード90 < 120はtrueなので、2番目の頭部が動き、中程度のテンポを表す1を返します。最後の頭部にはガードが無く、そこまで来たすべてのものを受け取ります。実行します。出力は1です。tempo_class(90)は最初の頭部を試し、ガード90 < 60がfalseなので、2番目に進みます。そのガード90 < 120はtrueなので、2番目の頭部が動き、中程度のテンポを表す1を返します。最後の頭部にはガードが無く、そこまで来たすべてのものを受け取ります。
多頭関数と match
多頭関数とmatchは関連したアイデアを表現します。matchは一つの関数本体の中で選びます。多頭関数はそもそもどの本体に入るかを選びます。ケース同士がそれぞれ独立した定義に値するくらい大きいときは多頭関数を、選択が一つの計算の中の小さな一歩であるときはmatchを使います。多頭関数とmatchは関連したアイデアを表現します。matchは一つの関数本体の中で選びます。多頭関数はそもそもどの本体に入るかを選びます。ケース同士がそれぞれ独立した定義に値するくらい大きいときは多頭関数を、選択が一つの計算の中の小さな一歩であるときはmatchを使います。
この章のまとめ
- 関数名はいくつかの頭部を持つことができ、各頭部が一つのケースを扱います。関数名はいくつかの頭部を持つことができ、各頭部が一つのケースを扱います。
- 頭部はリテラルの引数に当てはまることも、束縛で受け取ることもできます。
- 頭部は
whenガードを持てます。 - 頭部は書かれた順に試され、最初に当てはまったものが使われるので、具体的なケースを一般的なケースより前に書きます。頭部は書かれた順に試され、最初に当てはまったものが使われるので、具体的なケースを一般的なケースより前に書きます。
これで第3部は完了です。構造体、列挙型、タプル、配列、matchによるデータの分解、そして関数を複数の頭部に分ける手段が使えるようになりました。第4部では言語の中心 — 3種類の関数と、プログラムがホストと話す仕組み — に進みます。これで第3部は完了です。構造体、列挙型、タプル、配列、matchによるデータの分解、そして関数を複数の頭部に分ける手段が使えるようになりました。第4部では言語の中心 — 3種類の関数と、プログラムがホストと話す仕組み — に進みます。