第九回
「リストの追加」
前回は Felleisen の C オペレータを実装しました。が、リストがないとあまり面白いプログラムが動かせませんねー
ということで、ちょっと横道にそれますがリストも実装します。
リストを実装って具体的に何するの?というと、
:: と、パターンマッチを実装します。
パターンマッチって大変そう、と思うかもしれませんが、
機能を限定したパターンマッチであればさほど難しくはありません。
今回は結構簡単です!
まずは、構文に Empty と Cons(first, rest) を加えましょう。
例えば 1 :: 2 :: [] は
Cons(Number 1, Cons(Number 2, Empty))
と書き表すようにします。
もちろん[1; 2; 3]のように書きたいわけですが、それは lexer/parser で処理します。
つまり、[1; 2; 3]のような入力が来たら、parser の中でそれを
Cons(Number 1, Cons(Number 2, Cons(Number 3, Empty)))
に変換して返すようにします。
また、リストの構文に対応して、value_t にも VEmpty と VCons(first, rest)を加えます。
で、Empty や Cons(..., ...) が来たら VEmpty, VCons(..., ...)を返すようにします。
あとはパターンマッチです。
match lst with
[] -> A
| a :: rest -> B
という構文を Match(lst, A, a, rest, B) と表すことにします。
OCaml ではもっと複雑なパターンマッチを書く事が出来ますが、
ここでは簡単のために match 文と言ったら上の形のようなもののみ受け付けることにします。
ここで lst, A, B は任意の式ですが、 a と rest は B の中で使える変数名(文字列)です。
インタプリタでは、この Match を受け取ったら、まず lst を評価し、
その値が VEmpty だったら A を実行、VCont(p, q) だったら B を、
「変数 a の値が p で、変数 rest の値が q である」という情報を付け加えた環境で実行します。
=========================================================
問題(質問、相談可)
リストを実装せよ。いろいろな例で動いていることを確認せよ。
=========================================================
なお、今回は match 文を導入する方法を示しましたが、
リストの先頭部分と残り部分を取ってくる関数 head, tail を実装するという方法もあります。
その場合、パターンマッチをするためには match 文のかわりに以下のように書きます。
if lst = empty
then A
else let a = head lst in
let rest = tail lst in
B