Vlrfsasm講習/関数

概要

Vlrfsasmは、純粋な関数型言語です。別の言い方をすれば、関数以外にプログラミング要素はありません。関数を使いこなすことができれば、Vlrfsasmでできることはほぼ全てできます。

エラーについて

本章以降、実行するとエラーが発生する可能性があります。指定した.logファイルに書き込まれているはずなので、エラーの章と一緒に読んでください。

定義

まずは関数の定義を学びましょう。

関数の要素
名前関数を他の関数と区別する識別子
引数実行前に関数に渡される値
返り値関数から実行後に返される値

名前

関数の名前には、制限があります。

規則良い例悪い例1悪い例2
単一の符であることgetSecondElementget element2getElement(second)
リテラルの形でないこと階乗"factorial"0x66
唯一の名前であることifContainedItifContainEditifcontainedit

引数

関数のうち、どのように呼び出しても同じ結果が返ってくるものを、定数関数といいます。

逆に言えば、定数関数以外の関数は、条件によって異なる結果を返します。この条件を関数に与えるのが引数です。ただし、Vlrfsasmにおいては、関数が使わない引数を持っていても構いません。

引数の数は1つの関数につき1通りのみです。全ての値が引数になれます。前章の通り、型はありません。また、1つの関数が17個以上の引数をもつことはできません。

引数の名前の規則は、前項に示した関数の名前の規則とほぼ同じです。ただし、他の関数の引数とは、名前が被っていても構いません。類似の関数であれば、引数名が共通であると読みやすいでしょう。

返り値

関数を実行すると、結果が返されます。Vlrfsasmにおいては、必ずちょうど1つの値を返さなくてはなりません。この値のことを返り値といいます。

構文

実際に関数を定義する構文は、以下の通りです。

関数定義COPIED!
  1. 引数をもつ定数関数
  2. {constA Dummy; ; 10}
  3. 引数を省略した定数関数
  4. {constB; ; "Hello!"}
  5. 第一引数の値を返す関数
  6. {functionA Argument Dummy; ; Argument}

ここで、関数名返り値が必ず存在し、引数が任意にあることがわかると思います。

定義位置

関数の定義位置は、言語によって異なります。

定義位置の主な例
A関数を呼び出す位置より前
Bプログラムの実行時より前
C関数を呼び出す時より前
Dプログラムが終了する前

VlrfsasmはCにあたります。実行されない関数は未定義であっても構わないのがBとの違いです。

出力関数

Vlrfsasmの実行結果は、ファイルで出力されます。この出力内容を定めるのが、出力関数です。

名前

出力関数の名前は、ピリオド1字.です。これは言語仕様なので、別の関数を出力関数にしたり、この名前を出力関数でないようにするといったことはできません。ただし、出力関数の中で別の関数を呼び出せば、前者は実質的に実現できます。

また、符がピリオド1字のみの場合が出力関数になるので、他の文字も含む名前は自由に使えます。

用法

出力関数は、他の関数と同じく1度しか定義できず、その返り値が実行結果として出力されます。つまり、Vlrfsasmで出力できる値は1つだけです。

Vlrfsasmは、ソースコードを解釈した後、出力関数を実行します。そして、返り値を決定できるまで、定義に含まれる関数を次々に呼び出します。他の関数から呼び出されるものではないので、引数はありません。引数を定義してしまうとエラーになる可能性があります。

呼び出し

ここまで断りもなく「呼び出し」という言葉を使ってきましたが、これについて解説します。関数の定義を先に説明しないと、例を実行できないためでした。

構文

関数を呼び出す構文は、「S式」というものを採用しています。これは、関数名と引数を、丸かっこ内にスペース区切りで並べるものです。あまり普及はしていませんが、Vlrfsasmの構文は他に関数定義のものしか必要としません。汎用性が高く、とても簡潔に書ける構文なのです。

例を見てみましょう。丸かっこ内の最初の符が関数名で、2つ目以降の符は引数です。なお、引数の個数はその関数の定義と一致する必要があります。順番も書いた順がそのまま割り当てられます。引数には、リテラル、呼び出し元関数の引数、または別の関数の返り値を指定できます。

関数呼び出しの例COPIED!
  1. {.; ; (funcA)}
  2. {funcA; ; (funcB 1234)}
  3. {funcB X; ;
  4. UTF-16BEからUTF-8への変換[UTF-8への変換関数]
  5. (c.convertSbS8
  6. 非負整数を10進文字列に変換[文字列への変換関数]
  7. (c.convertISb X 10)
  8. )
  9. }

スタック

動作の面から言うと、Vlrfsasmはスタックマシンです。関数の呼び出し時の引数は、その関数内で別の関数を呼び出したり、自己再帰をしても、変化しません。

スタックの深さには限りがあり、現在は127段以上の呼び出しができません。再帰を使う際には注意してください。

テスト

文章を読むだけではつまらないので、簡単な問題を付けておきます。

問1

関数+は、定義済みの関数で、加算を表します。この関数は、例外的に可変個の引数を持ちます。1個以上ならいくつでもよいのです。

さて、これを用いて計算をしましょう。非負整数をいくつか決めてください。そして、その和をもとめ、10進文字列にしてUTF-8形式で出力してください。ただし、和は1.8×1019以下になるようにしましょう。

問2

関数f(x)=2x+5を定義してください。なお、関数名等との区別をつけるため、引数名は大文字で始めるとよいでしょう。結果も問1と同様に出力してください。

乗算関数も定義できますが、今回は使わないでやってみましょう。