上川純
一
![]() |
ocaml はフランス界隈で流行っている言語のようです。 advi や unison などのかゆいところに手が届く感じのソフトウェアが ocaml で実装されていて、 気にはなっていました。 ocaml は素晴らしい計算機理論を活用して最新の何かが実装されていると いう噂は聞いているのですが、 いまいち何がどうすごいのかよくわからないのでものは試しと、 試してみま した。
Debian GNU/Linux には ocaml 関連のパッケージが多数入っています。 ためしに検索してみると 224 パッケージありました。
$ apt-cache search ocaml | wc -l
224 |
ocaml にはインタラクティブに使うためのインタプリタと、 バイナリを生成してくれるコンパイラの両方があります。 ocaml をとりあえず一通り使うためには ocaml のインタプリタとコンパイラがあればよさそうです。 ocaml のネイティブコード用の コンパイラは ocaml-native-compilers パッケージのようです。 ocaml のインタープリタは ocaml-interp パッケージのよう です。
emacs ユーザとしては、 emacs 用のモードも必要です。 emacs のモードでそのものずばりの ocaml-mode というものもある のですが、 tuareg というのがよさそうなので、 それをインストールしてみました。
# apt-get install tuareg-mode ocaml-native-compilers ocaml-interp ocaml
|
インタラクティブに ocaml を使って見ました。 まず足し算をしてみます。
emacs から M-x tuareg-run-caml で ocaml のインタラクティブな端末 (ocaml 用語では「トップレベル」 という) を起動し ました。 足し算をするには、 1 + 2 を入力し、 文の終了は ’;;’ で表現します。
# 1 + 2 ;;
- : int = 3 |
int 型の 3 がかえってきました。 めでたしめでたし。
では、 関数を定義してみます。
# let my_func a b = a + b ;;
val my_func : int -> int -> int = <fun> # my_func 2 3;; - : int = 5 |
int int をとって int をかえす関数が定義され、 それを 2 と 3 で呼び出したら 5 が帰って来ました。
めでたしめでたし。
型をまったく宣言していないですが、 勝手に定義されているあたりが型推論機能のようです。 どうして型が推論できるかとい うことを疑問に思われるかもしれませんが、 「+」 は実は int 専用の足し算です、 float の場合は「+.」 を使うそうです。 これを 知って失神しそうになりました。
とりあえずインタラクティブに使う方法はわかったので、 コンパイルして使う方法を見てみましょう。 ocaml は中間言語に変 換する方法とネイティブコンパイルする方法の二つがあるようです。 ocamlc は中間言語、 ocamlopt はネイティブコン パイラのようです。 ocamlc には二種類のバイナリが提供されており、 ocamlc と ocamlc.opt があります。 ややこしいですが、 ocamlc.opt はネイティブコンパイラーでコンパイルした中間言語コンパイラーのよう です。
$ time ocamlc fibo.ml -o a.1
real 0m0.038s user 0m0.032s sys 0m0.004s $ time ocamlc.opt fibo.ml -o a.2 real 0m0.014s user 0m0.012s sys 0m0.000s |
種類を表 1にまとめてみました。
|
簡単な fibonacci のコードを書いてみて動作速度の雰囲気を感じてみました。 バイトコードのオーバヘッドが感じられる結果 になりました。
$ time ./byte-code
102334155 real 0m14.544s user 0m14.541s sys 0m0.000s $ time a./native-code 102334155 real 0m2.933s user 0m2.932s sys 0m0.000s $ time ./fibo.c 40 102334155 real 0m2.325s user 0m2.192s sys 0m0.040s |
Debian パッケージにする際には、 コンパイルする回数よりもインストールして実行される回数のほうが多いため、 基本として はネイティブコンパイルを選択します。 ただし、 ネイティブコンパイルできない CPU アーキテクチャもあるため、 どのコンパ イラを利用するのかを抽象化するレイヤーが必要です。
ocaml packaging policy によると、 ネイティブコンパイラに対応しているのは amd64, i386, kfreebsd-i386, powerpc, sparc だけだそうです。 重要なアーキテクチャで動きません。 たとえば、 arm、 superh、 mips などには対応してないよう です。
ライブラリの扱いは特殊で、 /usr/lib/ocaml/3.10.2/以下においてあるようです。 ライブラリといっても、 バイナリの libxxx.so 共有ライブラリがおいてあるわけではなく、 .mli インタフェースファイルが大量においてあります。 ocamlc -where で発見できるようです。
$ ocamlc -where
/usr/lib/ocaml/3.10.2 |
ひどい点は、 年に一回くらいマイナーバージョンがリリースされているのですが、 その度にライブラリコードがバイナリ非互 換に変更されているっぽく、 リビルドするハメになっているようです。
Debian の ocaml メンテナンスチームはあらゆるパッケージを一つの subversion リポジトリに統合して管理しているようで すが、 その理由の一つがこのバージョン間の非互換性ではないでしょうか。
Debian 勉強会資料
2009 年 4 月 18 日 初版第 1 刷発行
東 京 エ リ ア
Debian 勉強会 (編集・印刷・発行)
__________________________