M.Hiroi's Home Page

Functional Programming

お気楽 OCaml プログラミング入門

[ Home | Functional ]

WHAT'S NEW


CONTENTS

お気楽 OCaml プログラミング入門と Yet Another OCaml Problems のフォントを Web フォント (Noto Sans JP, Noto Sans Mono) に変更し、印刷用の CSS を追加しました。Web ブラウザの印刷機能を使って PDF に変換することもできます。表示が崩れるときはフォント Noto Sans Mono CJK JP をインストールしてください。


お気楽 OCaml プログラミング入門

CONTENTS


はじめに

OCaml は ML (Meta Language) という関数型プログラミング言語の一つです。ML は 1970 年代後半に Edinburgh 大学で定理証明を行うシステム Edinburgh LCF を記述するため、R. Minler 博士を中心に開発された言語です。その後、改良が重ねられ、いくつかの ML 処理系が作られました。その中で有名なのが SML/NJ (Standard ML of New Jersey) と OCaml (Objective Caml) です。Caml はフランスの INRIA 研究所で開発された ML 処理系で、そこにオブジェクト指向機能を加えたものが OCaml です。

UNIX 系 OS の場合、OCaml のインストールはパッケージマネージャを使うと簡単です。たとえば、Ubuntu であれば以下のコマンドでインストールすることができます。

sudo apt install ocaml

ただし、これでインストールされるのは少し古いバージョン (4.13.1, 2024 年 10 月現在) です。最新のバージョンをインストールする場合は OCaml のパッケージマネージャ OPAM を使用するようです。以下のページが参考になると思います。

Windows の場合、WSL (Windows Subsystem for Linux) もしくは Cygwin を使ったほうが簡単です。M.Hiroi は WSL2 で Ubuntu 22.04 を使っています。Cygwin には OCaml のパッケージが用意されているので、それをインストールするだけです。

●OCaml の特徴

関数型言語というと Lisp (Common Lisp, Scheme) が有名です。Lisp の場合、データに型はありますが、変数に型はありません。これに対し ML は強く型づけされた言語で、コンパイル時に静的な型チェックを行うことで、多くのエラーを検出することができます。

ML で一番有名な機能は「型推論」でしょう。ML はプログラムから変数などのデータ型を見つけてくれるので、プログラマが型を宣言する必要はほとんどありません。推論できない場合にかぎり、ML は型宣言を要求します。この機能により、ML は静的な型チェックを行う「型付きの言語」でありながら、 Lisp のような柔軟なプログラミングが可能になっています。

この他にも、パターンマッチング、多相型関数、モジュールなど、ML には興味深い機能がたくさんあります。なお、このような特徴は SML/NJ と OCaml で大きな違いはありませんが、文法面ではかなりの違いがあります。ご注意ください。

●プログラムの実行

OCaml はプログラムをコンパイルしてから実行します。OCaml のコンパイラは対話式コンパイラとバッチコンパイラの二種類があります。たとえば、シェルで対話式コンパイラ (ocaml) を起動すると、メッセージとプロンプト # が表示されます。この状態で OCaml のプログラムを入力して簡単に実行することができます。終了する場合は #quit;; と入力してください。

なお、ocaml にはコマンドラインの編集やコマンド履歴をたどる機能がありません。この場合、rlwrap をインストールすると便利になります。

sudo apt install rlwrap

あとはシェルで rlwrap ocaml を実行するだけです。簡単なプログラムであれば、これだけでもかなり便利になります。

バッチコンパイラはプログラムをコンパイルして実行可能ファイル (executable file) を生成します。バッチコンパイラは、プログラムをバイトコードにコンパイルする ocamlc と、ネイティブコード (機械語) にコンパイルする ocamlopt の二種類があります。バイトコードにコンパイルされたファイルは、バイトコードインタプリタによって実行されますが、ネイディブコードにコンパイルされたファイルは単独で実行することができます。

●簡単なベンチマーク

OCaml はネイティブコードにコンパイルすると、当然ですがプログラムを高速に実行することができます。また、バイトコードにコンパイルする場合でも、スクリプト言語やバイトコードにコンパイルする Lisp 処理系よりも速いようです。そこで、たらいまわし関数を使って実行速度を比較してみました。

リスト : たらいまわし関数

let rec tak x y z = 
  if x <= y then z
  else
    tak (tak (x - 1) y z) (tak (y - 1) z x) (tak (z - 1) x y)

(* 時間計測 *)
let () = 
  let a = Sys.time () in
    ignore (tak 22 11 0);
    print_float (Sys.time () -. a)

(* ... *) はコメントを表します。OCaml の場合、コメントは入れ子になってもかまいません。ファイル名を tak.ml とすると、コンパイルは次のように行います。

$ ocamlc -o tak tak.ml

$ ./tak

これで実行ファイル tak が作成されます。あとはそのまま実行するだけです。自動的にバイトコードインタプリタが呼び出されてプログラムが実行されます。ocamlopt の場合も同様にコンパイルすることができます。

それでは実行結果を示します。tak 22 11 0 を計算しました。

表 : tak 22 11 0 の結果
処理系
Python (ver 3.10.12)62.23
Ruby (ver 3.0.2p107)25.59
Lua (ver 5.4.4)22.41
Gauche (ver 0.9.15)21.29
ocamlc (ver 4.13.1)9.46
SBCL (ver 2.1.11)4.90
Julia (ver 1.10.5)1.84
SBCL (最適化)1.50
GCC -O2 (ver 11.4.0)1.19
ocamlopt (ver 4.13.1)1.05

ocamlopt が gcc よりも速いとは驚きました。gcc のコンパイルオプションは -O2 を指定しただけなので、他のオプションを指定するともう少し速くなるかもしれません。興味のある方は試してみてください。

バイトコードにコンパイルする場合でも、OCaml は他の処理系より高速です。たらいまわし関数のように、再帰呼び出しの回数が多いテストは関数型言語に有利だったかもしれません。そうだとしても、OCaml のコンパイラは優秀だと思います。

●Enjoy Programming!!

M.Hiroi は OCaml でプログラミングするのは初めてです。このページで簡単なプログラムを作りながら OCaml を勉強していきたいと思っております。たいしたことはできませんが、よろしくお付き合いくださいませ。


初版 2008 年 6 月 7 日
改訂 2024 年 10 月 25 日

Yet Another OCaml Problems


参考文献, URL

●参考文献

  1. 五十嵐淳, 『プログラミング in OCaml』, 技術評論社, 2007

●参考 URL

  1. OCaml - OCaml, (本家)
  2. OCamlチュートリアル - OCaml, (本家, 日本語訳)
  3. Objective Caml 入門 (PDF), (五十嵐淳さん)
  4. 数理科学的バグ撲滅方法論のすすめ | 日経クロステック, (住井英二郎さん)
  5. OCaml.jp, "Objective Caml に関する情報を集めたコミュニティサイト" とのことです。

『お気楽 OCaml プログラミング入門』の著作権は筆者「広井誠 (Makoto Hiroi)」が保持します。無断使用や無断転載は禁止いたします。お気楽 OCaml プログラミング入門で作成したプログラムはフリーソフトウェアとします。ご自由にお使いください。プログラムの改造や配布もご自由にどうぞ。その際は、出典を明記してくださるようお願いいたします。

ただし、これらのプログラムは無保証であり、使用したことにより生じた損害について、作者「広井誠 (Makoto Hiroi)」は一切の責任を負いません。また、これらのプログラムを販売することで利益を得るといった商行為は禁止いたします。

Copyright (C) 2008-2024 Makoto Hiroi
All rights reserved.

[ Home | Functional ]