Vlrfsasmは、純粋な関数型言語です。別の言い方をすれば、関数以外にプログラミング要素はありません。関数を使いこなすことができれば、Vlrfsasmでできることはほぼ全てできます。
本章以降、実行するとエラーが発生する可能性があります。指定した.logファイルに書き込まれているはずなので、エラーの章と一緒に読んでください。
まずは関数の定義を学びましょう。
名前 | 関数を他の関数と区別する識別子 |
引数 | 実行前に関数に渡される値 |
返り値 | 関数から実行後に返される値 |
関数の名前には、制限があります。
規則 | 良い例 | 悪い例1 | 悪い例2 |
単一の符であること | getSecondElement | get element2 | getElement(second) |
リテラルの形でないこと | 階乗 | "factorial" | 0x66 |
唯一の名前であること | ifContainedItとifContainEdit | ifcontainedit |
関数のうち、どのように呼び出しても同じ結果が返ってくるものを、定数関数といいます。
逆に言えば、定数関数以外の関数は、条件によって異なる結果を返します。この条件を関数に与えるのが引数です。ただし、Vlrfsasmにおいては、関数が使わない引数を持っていても構いません。
引数の数は1つの関数につき1通りのみです。全ての値が引数になれます。前章の通り、型はありません。また、1つの関数が17個以上の引数をもつことはできません。
引数の名前の規則は、前項に示した関数の名前の規則とほぼ同じです。ただし、他の関数の引数とは、名前が被っていても構いません。類似の関数であれば、引数名が共通であると読みやすいでしょう。
関数を実行すると、結果が返されます。Vlrfsasmにおいては、必ずちょうど1つの値を返さなくてはなりません。この値のことを返り値といいます。
実際に関数を定義する構文は、以下の通りです。
- 引数をもつ定数関数
- {constA Dummy; ; 10}
- 引数を省略した定数関数
- {constB; ; "Hello!"}
- 第一引数の値を返す関数
- {functionA Argument Dummy; ; Argument}
ここで、関数名と返り値が必ず存在し、引数が任意にあることがわかると思います。
関数の定義位置は、言語によって異なります。
A | 関数を呼び出す位置より前 |
B | プログラムの実行時より前 |
C | 関数を呼び出す時より前 |
D | プログラムが終了する前 |
VlrfsasmはCにあたります。実行されない関数は未定義であっても構わないのがBとの違いです。
Vlrfsasmの実行結果は、ファイルで出力されます。この出力内容を定めるのが、出力関数です。
出力関数の名前は、ピリオド1字.です。これは言語仕様なので、別の関数を出力関数にしたり、この名前を出力関数でないようにするといったことはできません。ただし、出力関数の中で別の関数を呼び出せば、前者は実質的に実現できます。
また、符がピリオド1字のみの場合が出力関数になるので、他の文字も含む名前は自由に使えます。
出力関数は、他の関数と同じく1度しか定義できず、その返り値が実行結果として出力されます。つまり、Vlrfsasmで出力できる値は1つだけです。
Vlrfsasmは、ソースコードを解釈した後、出力関数を実行します。そして、返り値を決定できるまで、定義に含まれる関数を次々に呼び出します。他の関数から呼び出されるものではないので、引数はありません。引数を定義してしまうとエラーになる可能性があります。
ここまで断りもなく「呼び出し」という言葉を使ってきましたが、これについて解説します。関数の定義を先に説明しないと、例を実行できないためでした。
関数を呼び出す構文は、「S式」というものを採用しています。これは、関数名と引数を、丸かっこ内にスペース区切りで並べるものです。あまり普及はしていませんが、Vlrfsasmの構文は他に関数定義のものしか必要としません。汎用性が高く、とても簡潔に書ける構文なのです。
例を見てみましょう。丸かっこ内の最初の符が関数名で、2つ目以降の符は引数です。なお、引数の個数はその関数の定義と一致する必要があります。順番も書いた順がそのまま割り当てられます。引数には、リテラル、呼び出し元関数の引数、または別の関数の返り値を指定できます。
- {.; ; (funcA)}
- {funcA; ; (funcB 1234)}
- {funcB X; ;
- UTF-16BEからUTF-8への変換[UTF-8への変換関数]
- (c.convertSbS8
- 非負整数を10進文字列に変換[文字列への変換関数]
- (c.convertISb X 10)
- )
- }
動作の面から言うと、Vlrfsasmはスタックマシンです。関数の呼び出し時の引数は、その関数内で別の関数を呼び出したり、自己再帰をしても、変化しません。
スタックの深さには限りがあり、現在は127段以上の呼び出しができません。再帰を使う際には注意してください。
文章を読むだけではつまらないので、簡単な問題を付けておきます。
関数+は、定義済みの関数で、加算を表します。この関数は、例外的に可変個の引数を持ちます。1個以上ならいくつでもよいのです。
さて、これを用いて計算をしましょう。非負整数をいくつか決めてください。そして、その和をもとめ、10進文字列にしてUTF-8形式で出力してください。ただし、和は以下になるようにしましょう。
関数を定義してください。なお、関数名等との区別をつけるため、引数名は大文字で始めるとよいでしょう。結果も問1と同様に出力してください。
乗算関数も定義できますが、今回は使わないでやってみましょう。