1.2 データ型

整数と浮動小数点数以外に、Caml には真偽値、文字、文字列の基本型があります。

#(1 < 2) = false;;
- : bool = false

#'a';;
- : char = 'a'

#"Hello world";;
- : string = "Hello world"
    

あらかじめ定義されているデータ構造として、タプル、配列、リストがあります。ユーザが自分でデータ構造を定義することも出来ます。ユーザー定義型については後で説明することにして、今はリストに集中しましょう。 リストは要素をセミコロンで区切りブラケットで囲んだ形で書くか、空リスト [] (nil と発音します)の前に :: (cons)演算子で要素を加える形で書くことが出来ます。

#let l = ["is"; "a"; "tale"; "told"; "etc."];;
val l : string list = ["is"; "a"; "tale"; "told"; "etc."]

#"Life" :: l;;
- : string list = ["Life"; "is"; "a"; "tale"; "told"; "etc."]
    

他の Caml のデータ構造と同じく、リストに関してメモリの確保・開放を自分でする必要はありません。メモリ管理はすべて自動的に行なわれます。同様にポインタを扱う必要もありません。コンパイラが必要に応じて暗黙のうちにポインタを導入します。

他の大半のデータ構造の同じく、リストの中を見たり分解したりするのにはパターンマッチを用います。 リストパターンはリスト式とまったく同じ形で、識別子でリストの未規定部分を表します。 例としてリストの挿入ソートを示します。

#let rec sort lst =
   match lst with
     [] -> []
   | head :: tail -> insert head (sort tail)
 and insert elt lst =
   match lst with
     [] -> [elt]
   | head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail
 ;;
val sort : 'a list -> 'a list = <fun>
val insert : 'a -> 'a list -> 'a list = <fun>

#sort l;;
- : string list = ["a"; "etc."; "is"; "tale"; "told"]
    

sort の型として推論された 'a list -> 'a list は、 sort は任意の型のリストでも引数にとれ、同じ型のリストを返すことを表しています。'a型変数(type variable)で、任意の型を表します。sort が任意の型のリストを受け取れるのは、Caml では比較演算子 (=<= など) が多相的(polymorphic)であるためです。これらの演算子は同一の型を持つふたつの値に作用します。

#sort [6;2;5;3];;
- : int list = [2; 3; 5; 6]

#sort [3.14; 2.718];;
- : float list = [2.718; 3.14]
    

上の sort 関数は入力として与えられたリストを変更せず、入力されたリストと同じ要素を昇順に並べたリストを新たに作って返します。実際 Caml では、一度作ったリストを直接変更する方法はありません。このことを、リストは変更不能(immutable)なデータ構造である、と言います。 Caml の大半のデータ構造は変更不能ですが、いくつかのデータ構造(有名なところでは配列)は変更可能(mutable)で、いつでも直接変更することができます。