見出し画像

初心者にやさしい言語OCamlでプログラミングを学んでいます(データ型定義)

 やさしくても「表現力と安全にこだわった仕事で使える関数型言語」OCamlによるプログラミング学習の第8回です。テキストは、公式ページのあの日からOCamlです。
 内容は、typeによるデータ型の定義についてのまとめです。

新しいデータ型

 OCamlでは、ユーザが新しいデータ型を定義できる。データ型の定義は、typeにより行う。


# type star = Sirius | Procyon | Alnath | HIP of int;;
type star = Sirius | Procyon | Alnath | HIP of int

# let lst = [Procyon; Alnath; HIP (97649)];;
val lst : star list = [Procyon; Alnath; HIP 97649]

 (この例では、starが型の名前になります。また、SiriusやHIPはコンストラクタと呼ばれ、star型の値を生成します。)

多相かつ再帰な定義

 定義するデータ型は、多相かつ再帰的なものでもよい。 
 これについて、二分木を例に説明する。この二分木は、任意の型のデータを保持する。


# type 'a tree = Leaf | Node of 'a tree *'a*'a tree;;
type 'a tree = Leaf | Node of 'a tree * 'a * 'a tree

# let tr = Node (Node (Leaf, 1, Leaf), 2, Node (Node (Leaf, 3, Leaf), 4, Leaf));;
val tr : int tree =
Node (Node (Leaf, 1, Leaf), 2, Node (Node (Leaf, 3, Leaf), 4, Leaf))

 葉は、値を保持せず、ノードは、左の木、'aの型の値、右の木を保持する。
 (多相と再帰は、of以降の定義により実現されています。具体的には、型変数'aで型を指定することで多相になり、treeを参照することで再帰的になります。)

パターンマッチング

 この木についての多相な再帰関数の例を以下に示す。関数は、コンストラクタを用いたパターンマッチングにより定義される。
 まず、各ノードが整数値を保持する木について、それらの値の合計を求める関数totalを示す。

定義
# let rec total tr = match tr with
| Leaf -> 0
| Node (left, data, right) -> total left+data+total right;;
val total : int tree -> int = <fun>
適用
# total tr;;
- : int = 10

次に、各ノードが保持する木を左右を反転させる関数flipを示す。

定義
# let rec flip tr = match tr with
| Leaf -> Leaf
| Node (left, data, right) -> Node (flip right, data, flip left);;
val flip : 'a tree -> 'a tree = <fun>
適用
# let flipped_tr = flip tr;;
val flipped_tr : int tree =
Node (Node (Leaf, 4, Node (Leaf, 3, Leaf)), 2, Node (Leaf, 1, Leaf))
元の木と二回適用した木の比較
# tr = flip flipped_tr;;
- : bool = true

GC

 ところで、OCamlはガーベージコレクションを備えた言語なので、プログラマは明示的に記憶領域を開放する必要がない。
 前の例では、tr = flp flipped_trの真偽判定された後は、flip flipped_trに到達できなくなるので、その記憶領域がGCにより回収される。
 (どう訛ったらガベージに聞こえるのだろう?)


まとめ

 今回は、typeによるデータ定義について学びました。
 ところで、見出し画像にフライドポテトを使いたいのですが、なかなか好みの画像が見つかりません。どれも白すぎたり茶色すぎたりして、食指が動きません。綺麗な写真とおいしそうな写真は違うので、写真は難しいです。自分で撮ってないのに偉そうですが。
 次回は、例外処理の予定です。



古往今来得ざれば即ち書き得れば即ち飽くは筆の常也。と云うわけで御座います、この浅ましき乞食めに何卒皆々様のご慈悲をお願い致します。