-
Objective Camlは,いわゆる関数型言語である
- 計算の仕組みは Scheme
に似ていて,式を値に評価することでプログラム実行が進む.例えば,Scheme
では,
(define (fact n)
(if (= n 0) 1 (* n (fact (- n 1)))))
(fact 5)
と入力すると,階乗関数 fact が定義されて,次の式の入力により
120 が返ってくるが,Objective Camlでは以下のように書く.
let rec fact n =
if n = 0 then 1 else n * fact (n-1);;
fact 5;;
何となく対応関係がわかるだろうか.
- 関数も値である
- もちろん,Scheme のように,関数を
返す関数や,関数を引数に取る関数なども自由に使える.例えば,以下は
与えられた関数 f と整数 n から ∑i=0n f(i)
を計算する関数である.
let rec sum (f, n) =
if n = 0 then f(n) else f(n) + sum (f, n-1);;
sum (fact, 5);;
とすると,0! + 1! + 2! + 3! + 4! + 5! が計算されて,154
が返ってくる.
- Objective Camlには静的型があり,強く型付けされる
- Objective Camlプログラムに対して
は実行前に型検査が行われ,演算子などの誤った使用がないかどうかが
検査される.型の合わない計算をさせようとすると,
実行をする前に(静的に)エラーが発生して誤りを指摘される.
let hoge x = x + 1 + "hoge";;
などと入力すると,その時点で,hoge を呼び出してもいないのに,
This expression has type string but is here used with type int
つまり,"hoge" という文字列が,+ という整数を期待している演算子の
引数として使われていますよ,という意味のメッセージ(ここではシステムか
らの返答を表すために斜体を使っている)とともにコンパイルエラーが発生す
る. (実際は "hoge"の下に下線がひかれて, This expression がどれな
のかも教えてくれる.)このエラーは, hoge を呼び出して実際に足し算が
行われようとする前に発生するのがミソである.また,Objective Camlでは,型検査
を通過した場合には,文字列と整数の足し算のようなエラーが実行時に発生し
ないことが,(数学的に)保証されている.このことを Objective Caml は強
く型付けされた(strongly typed)言語である,という.
- Objective Camlは型推論をしてくれる
- C言語にも静的型があるが,
関数宣言の際に,仮引数の型を宣言する必要がある.これに対して
Objective Camlでは上の例からも見てとれるように,引数の型や返り値の型
をいちいち書かなくても,システムが推論をしてくれる.例えば,
let rec fact n =
if n = 0 then 1 else n * fact (n-1);;
とすると,システムからは,
val fact : int -> int = <fun>
という反応が返ってくる.これは fact が整数(int)を受け取って,
整数を返す関数(->)だということを示している.
- Objective Camlにはパターンマッチ機能がある
Objective Caml には,パターンマッチという機能があって,リストなど
構造のある値に対して,パターンを当てはめて,値の一部を取りだすこと
ができる.Objective Caml では,リストを [] (空リスト),:: (cons)
を使って, 1 :: 2 :: 3 :: [] のように書くのだが2,整数リストの先頭2要素までの和を計算
する関数 sum_of_first_two は,パターンマッチを使うと
let sum_of_first_two l =
match l with
[] -> 0
| x :: [] -> x
| x :: y :: rest -> x + y;;
val sum_of_first_two : int list -> int = <fun>
と書ける. match は関数の引数 l に対して,[] (空リストパターン)や
x::[] (1要素パターン) や x::y::rest (2要素以上パターン)
を当てはめて, 当てはまったら,変数 x (や y)
をリストの要素として,計算を行う.パターンマッチを使うと,条件分岐を複
雑に入れ子にすることなく,全ての場合が一度に書き下せるのが魅力である.
ちなみに,型に現れる -> の左側の int listは整数が並んだリスト が引
数としてとれることを示している.
- Objective Caml の型は多相的
- 多相的,というのは,ひとつのプログラムの
型がいろいろ変化することを示している.例えば,以下は,リストの長さを計算する関数であるが,
let rec length list =
match list with
[] -> 0
| x::rest -> 1 + length rest;;
これは,整数のリストに使うこともできるし,文字列のリストに使うこともできる.
length (2::3::4::[]);;
- : int = 3
length ("hoge"::"foo"::"bar"::"baz"::[]);;
- : int = 4
つまり,ひとつの関数 length を,「整数リストを受けとって整数を返す」
関数や「文字列リストを受けとって整数を返す」関数という別の型のものとして
使える.ソーティング関数なども,整数のソーティング,文字列のソーティングなど
異なる種類のデータに対するソーティングを,ひとつの定義で記述することができる.
このようなプログラミングを,型が多相的でない C
言語などで(安全性を損なわないで)行うのは難しい.
- その他の特徴
- Scheme と同様,ごみ集め(garbage collection)により,自動メモリ管理が行われるため,プログラマは C 言語の malloc/free などを使ったメモリ管理のように
頭を悩ませる必要がない.また,対話的にプログラム開発ができるインタラクティブ・コンパイラと,
ソースコードを一括して実行形式に変換するバッチ・コンパイラが利用できる.