OCaml
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2026/04/10 20:01 UTC 版)
| 登場時期 | 1996年[1] |
|---|---|
| 開発者 | フランス国立情報学自動制御研究所 (Inria) |
| 最新リリース | 5.4.0[2] |
| 型付け | 強い静的型付け、型推論、構造的型付け |
| 影響を受けた言語 | C、Caml、Modula-3、Pascal、Standard ML |
| 影響を与えた言語 | ATS、Rocq(旧称: Coq)、Elm、F#、F*、Haxe、Opa 、Rust[3]、Scala、Gleam |
| プログラミング言語 | OCaml、C |
| プラットフォーム | クロスプラットフォーム: Linux、Unix、macOS、Windows |
| ライセンス | LGPLv2.1 |
| ウェブサイト | 公式ウェブサイト |
| 拡張子 | .ml, .mli |
| 関連言語 | ML: Caml |
OCaml(オーキャムル、オーキャメル、旧称: Objective Caml)は、汎用、高水準、マルチパラダイムのプログラミング言語であり、MLのCaml方言にオブジェクト指向の機能を追加したものである。1996年にグザヴィエ・ルロワ、ジェローム・ヴイヨン[4]、ダミアン・ドリジェ、ディディエ・レミ[5]、Ascánder Suárezらによって開発された。
OCamlのツールチェーンには、対話型のトップレベルインタプリタ、バイトコードコンパイラ、最適化を行うネイティブコードコンパイラ、リバーシブルなデバッガ、パッケージ管理システム(OPAM)、および組み合わせ可能なビルドシステム(Dune)が含まれている。OCamlは当初、自動定理証明の文脈で開発され、静的解析や形式手法のソフトウェアで利用されている。これらの分野を超えて、システムプログラミング、Web開発、特定の金融ユーティリティなど、様々なアプリケーション領域で活用されている。
名称の「CAML」は元々「Categorical Abstract Machine Language(圏論的抽象機械言語)」の頭字語であったが、OCamlではこの抽象機械を省略している[6]。OCamlはフランス国立情報学自動制御研究所(Inria)によって管理および主に保守されているフリーかつオープンソースのプロジェクトである。2000年代初頭、OCamlの要素は多くの言語、特にF#やScalaなどに採用された。
設計思想
ML派生の言語は、その静的な型システムと型推論コンパイラで最もよく知られている。OCamlは、ML風の型システムの下で関数型、命令型、およびオブジェクト指向のパラダイムを統合している。そのため、プログラマはOCamlを使用するにあたって、純粋関数型言語のパラダイムに精通している必要はない。
プログラマに対し、その静的型システムの制約内で作業することを要求することにより、OCamlは動的型付け言語によく見られる型に関連した実行時の多くの問題を排除する。また、OCamlの型推論コンパイラは、多くの静的型付け言語で必要とされる手動による型アノテーションの必要性を大幅に減らす。たとえば、変数のデータ型や関数の型シグネチャは、コード内の変数や他の値に適用される演算子や他の関数から推論できるため、JavaやC#などの言語のように明示的に宣言する必要がない場合が多い。OCamlの型システムを効果的に使用するには、プログラマに一定の熟練が求められることがあるが、この規律は信頼性の高い高性能なソフトウェアという形で報われる。
学術界に起源を持つ他の言語と比較して、OCamlを最も特徴づけているのはパフォーマンスへの重点かもしれない。その静的型システムは実行時の型の不一致を防ぐため、動的型付け言語のパフォーマンスの負担となる実行時の型チェックや安全性チェックを不要にしつつも、配列の境界チェックをオフにした場合や、シリアライズのような型安全でない機能を使用した場合を除いて、実行時の安全性を保証する。これらは極めて稀であるため、実際には避けることが十分に可能である。
型チェックのオーバーヘッドを別としても、関数型言語は一般に、Funarg問題などの問題により、効率的な機械語コードにコンパイルするのが難しい。標準的なループ、レジスタ、命令の最適化に加えて、OCamlの最適化コンパイラは静的プログラム解析手法を用いて値のボクシング(boxing)とクロージャの割り当てを最適化し、関数型プログラミングの構造を多用した場合でも、生成されるコードのパフォーマンスを最大化するよう支援する。
グザヴィエ・ルロワは「OCamlは、まともなCコンパイラの少なくとも50%のパフォーマンスを発揮する」と述べているが[7]、直接的な比較は不可能である。OCamlの標準ライブラリのいくつかの関数は、他の言語の標準ライブラリにおける同等の関数よりも高速なアルゴリズムで実装されている。たとえば、OCaml標準ライブラリにおける集合の和集合の実装は、OCamlの実装が集合の不変性(immutability)を利用して入力集合の一部を出力で再利用できるため(永続データ構造を参照)、理論的には命令型言語(C++、Javaなど)の標準ライブラリにおける同等の関数よりも漸近的に高速である。
歴史
ML(Meta Language)の開発
1970年代から1980年代にかけて、イギリスの計算機科学者でありチューリング賞受賞者のロビン・ミルナーは、エディンバラ大学の計算機科学基礎研究所で研究を行っていた[8][9]。ミルナーらは定理証明器の開発に取り組んでおり、これらは歴史的にLispなどの言語で開発されていた。ミルナーは、定理証明器が証明ではないものを組み合わせることで証明が有効であると主張しようとする問題に繰り返し直面した[9]。その結果、彼は自身の計算可能関数ロジック(LCF)のためのメタ言語(meta language)を開発することになった。これは多相型システムによって、プログラマが有効な証明のみを構築できるようにする言語であった[10]。MLは、異なるマシンでのLCFの使用を簡素化するためにコンパイラへと変えられ、1980年代までにはそれ自体が完全なシステムとなった[10]。MLは最終的にOCamlの基盤として機能することになる。
1980年代初頭、フランス国立情報学自動制御研究所(Inria)のFormelチームがMLに関心を持つきっかけとなるいくつかの進展があった。オックスフォード大学の研究教授であったルカ・カルデリは、自身の「関数型抽象機械(functional abstract machine)」を使用してMLのより高速な実装を開発し、ロビン・ミルナーは様々な実装間の相違を避けるためにMLの新しい定義を提案した。同時に、パリ・ディドロ大学(現・パリ・シテ大学)の上級研究員であったピエール=ルイ・キュリアン(Pierre-Louis Curien)は圏論的コンビネータ(categorical combinators)の計算を開発し、それをラムダ計算に結びつけた。これにより「圏論的抽象機械(CAM)」の定義が導かれた。パリ・ディドロ大学の研究者ガイ・クジノー(Guy Cousineau)は、これがMLのコンパイル手法として適用できることを認識した[11]。
初期の実装
Camlは、ジェラール・ユエ率いるInriaのFormelチームによって最初に設計および開発された。Camlの最初の実装は1987年に作成され、1992年までさらに開発が続けられた。開発はAscánder Suárezによって主導されていたが、1988年に彼が去った後はピエール・ワイスとミシェル・モーニー(Michel Mauny)が開発を引き継いだ[11]。
Caml Light
1990年から1991年にかけて、グザヴィエ・ルロワはC言語で書かれたバイトコードインタプリタに基づくCamlの新しい実装を設計した。これに加えて、ダミアン・ドリジェはこの実装のために、シーケンシャルなガベージコレクションとして知られるメモリ管理システムを記述した[10]。Caml Lightとして知られるこの新しい実装は、古いCamlの実装を置き換え、小型のデスクトップマシンで動作した[11]。その後数年で、ミシェル・モーニーの構文操作ツールなどのライブラリが登場し、教育や研究チームでのCamlの使用を促進するのに役立った[10]。
Caml Special Light
1995年、グザヴィエ・ルロワはCamlの改良版であるCaml Special Lightをリリースした[11]。バイトコードコンパイラに最適化されたネイティブコードコンパイラが追加され、これによりパフォーマンスがC++などの主要言語と同等レベルにまで大幅に向上した[10][11]。また、ルロワはStandard MLのモジュールシステムに触発された高水準モジュールシステムを設計した。これにより、抽象化とパラメータ化のための強力な機能が提供され、より大規模なプログラムの構築が容易になった[10]。
Objective Caml
ディディエ・レミとジェローム・ヴイヨンは、オブジェクトとクラスのための表現力豊かな型システムを設計し、それがCaml Special Lightに統合された。これにより、1996年に初めてリリースされたObjective Caml言語が誕生し、後に2011年にOCamlへと改名された。このオブジェクトシステムは、C++やJavaなどの言語では型の不健全性(unsoundness)を引き起こしたり、実行時のチェックを必要としたりするような、普及している多くのオブジェクト指向のイディオムを、静的かつ型安全な方法でサポートしていた。2000年にジャック・ガリグ(Jacques Garrigue)は、多相メソッド、バリアント、ラベル付きおよびオプションの引数など、複数の新機能でObjective Camlを拡張した[10][11]。
継続的な開発
増大するOCamlの商業的および学術的なコードベースをサポートするため、過去20年間にわたり言語の改善が段階的に追加されてきた[10]。2012年のOCaml 4.0のリリースでは、言語の柔軟性を高めるために、一般化代数的データ型(GADT)とファーストクラス・モジュールが追加された[10]。2022年のOCaml 5.0.0リリース[12]は言語ランタイムの完全な書き直しであり、グローバル・インタプリタ・ロック(グローバルGCロック)が削除され、限定継続(delimited continuations)を介したエフェクトシステム(effect handlers)が追加された。これらの変更により、それぞれ共有メモリ並列処理と、カラーブラインド並行性(color-blind concurrency)のサポートが可能になる。
OCamlの開発は2005年までInriaのCristalチーム内で行われていたが、その後Galliumチームに引き継がれた[13]。続いて、2019年にGalliumはCambiumチームに引き継がれた[14][15]。2023年現在、コンパイラ配布のコア開発者は様々な組織からの23名で構成されており[16]、幅広いOCamlツーリングおよびパッケージング・エコシステムには41名の開発者がいる[17]。2023年、OCamlコンパイラはSIGPLAN(ACM SIGPLAN Programming Languages Software Award)を受賞した。
特徴
OCamlは、静的な型システム、型推論、パラメトリック多相性、末尾再帰、パターンマッチング、ファーストクラスの静的クロージャ、ファンクタ(パラメータ化されたモジュール)、例外処理、エフェクトシステム(effect handling)、およびインクリメンタルな世代別ガベージコレクションを特徴としている。
OCamlは、汎用言語においてMLスタイルの型推論をオブジェクトシステムに拡張していることで知られている。これにより、宣言された継承に関係なく、メソッドのシグネチャが互換であればオブジェクト型に互換性があるという、構造的型付け(structural subtyping)が可能になる(これは静的型付け言語では珍しい機能である)。
CやFORTRANと互換性のある形式の効率的な数値配列(array)の言語サポートを含む、C言語のプリミティブをリンクするためのForeign function interface(FFI)が提供されている。OCamlは、Cの「main」プログラムにリンクできるOCaml関数のライブラリの作成もサポートしており、OCamlの知識がない、またはインストールしていないCプログラマにもOCamlライブラリを配布することができる。
OCamlには、言語の不可分な一部としてのマクロシステム(メタプログラミング)、すなわちプリプロセッサによる前処理の組み込みサポートはないが、OCamlプラットフォームは公式に、そのようなプリプロセッサを記述するためのライブラリをサポートしている。これらには2つの種類がある。1つは(C言語のように)ソースコードレベルで機能するもの、もう1つは抽象構文木(AST)レベルで機能するものである。後者は「PPX」(Pre-Processor eXtensionの略)と呼ばれ、推奨されている方式である。
OCamlのディストリビューションには以下が含まれる:
- ocamllexおよびocamlyaccと呼ばれる字句解析および構文解析ツール
- エラーを調査するためのバックワード・ステップ(巻き戻し実行)をサポートするデバッガ
- ドキュメント・ジェネレータ
- パフォーマンスを測定するためのプロファイラ
- 多くの汎用ライブラリ
ネイティブコードコンパイラは、UNIX、Microsoft Windows、Apple macOSを含む多くのプラットフォームで利用できる。主要なアーキテクチャに対するネイティブコード生成のサポートにより、移植性が実現されている:
- x86-64 (AMD64)、RISC-V、およびARM64(OCaml 5.0.0以降)[18]
- IBM Z(OCaml 5.0.0以前、およびOCaml 5.1.0で復活)
- Power(OCaml 5.0.0以前、OCaml 5.2.0で再登場予定)
- IA-32およびARM(OCaml 5.0.0以前)
- SPARC(OCaml 4.06.0以前)
- DEC Alpha、HPPA、IA64、およびMIPS(OCaml 4.00.0以前)
バイトコードコンパイラは、ネイティブコード生成が利用できない場合でも、Cコンパイラさえあれば、任意の32ビットまたは64ビットアーキテクチャでの動作をサポートする。
OCamlのバイトコードおよびネイティブコードプログラムは、プリエンプティブなコンテキストスイッチを備えたマルチスレッドスタイルで記述できる。同じドメイン[19]内のOCamlスレッドは、タイムシェアリングによってのみ実行される。ただし、1つのOCamlプログラムには複数のドメインを含めることができる。
その他の派生実装および方言
Caml Light
前述の通り、OCamlの前身である実装。正確には名前だけでなく、新しい手法で再実装されたものであり、OCamlよりCaml Lightのほうが古くからある。現在もCaml Lightとして配布され続けている。
MinCaml
MinCamlは、ペンシルベニア大学(当時)の住井英二郎がOCamlで実装した、Caml似のMLの小型版である。同作者により、コンパイラがOCaml自身で書かれている。MinCamlは、2004年度の未踏ソフトウェア創造事業に採択された。
MinCamlコンパイラは教育目的での利用を主眼としている。わずか2000行前後のコードで書かれており、実装されている機能はMLのサブセットである。バックエンドはSPARCとx86に対応しており、ある程度の学習をすれば比較的容易に改造を行うことができる(有志によってPowerPC用に出力できるバージョンも提供されている。バックエンドをLLVMに置き換えた例も報告されている[20])。実際に東京大学理学部情報科学科などで教育目的に利用され、国内におけるOCamlおよび関数型言語の普及と理解に一定の役割を果たしている[要出典] 。
- 速攻MinCamlコンパイラ概説 - MinCamlの配布・解説(
SourceForge.net)
Moscow ML
CamlやOCamlのような方言ではなく、SML(Standard ML)の処理系の実装にCaml Lightを利用している。完全なSMLを実装する。
その他
OchaCamlなど、研究用の改造のベースとして、規模の大きくなったOCamlではなくCaml(Caml Light)を利用する例がみられる。
派生言語
MetaOCaml
MetaOCaml[21] は、実行中に新しい機械語コードのインクリメンタルなコンパイルを可能にする、OCamlの多段階プログラミング拡張である。いくつかの状況下では、多段階プログラミングを使用することで大幅な高速化が可能になる。これは、通常のコンパイル時よりも実行時の方が処理するデータに関する詳細な情報が得られるため、インクリメンタルコンパイラが条件チェックなどの多くのケースを最適化して排除できるためである。
例として、コンパイル時に何らかの冪乗関数x -> x^nが頻繁に必要になることがわかっているが、nの値はランタイム時にしかわからない場合、MetaOCamlでは2段階の冪乗関数を使用できる。
let rec power n x =
if n = 0
then .<1>.
else
if even n
then sqr (power (n/2) x)
else .<.~x *. .~(power (n - 1) x)>.
実行時にnが判明するとすぐに、特化された非常に高速な冪乗関数を作成できる。
.<fun x -> .~(power 5 .<x>.)>.
その結果、以下のようになる。
fun x_1 -> (x_1 *
let y_3 =
let y_2 = (x_1 * 1)
in (y_2 * y_2)
in (y_3 * y_3))
新しい関数は自動的にコンパイルされる。
その他の派生言語
プログラム例
以下の例は、プログラム自体としてはMLと比べ特別なものでもないし、オブジェクト指向を活用したものでもないが、OCamlを含むCamlでは旧来のMLやStandard MLからの記法や演算子や名前の変更が多く、簡単なプログラムでもそのままではエラーになるものが多いので、ここではOCamlのコードを示す。
特徴として、型推論の活用により、多くの場合に型の宣言が必要なく、一部の静的型付き言語にありがちな煩雑さがないことが挙げられる。
OCamlのコード・スニペットは、トップレベルの対話型環境(REPL)に入力することで最も簡単に学習できる。これは、結果または定義された式の推論された型を出力する対話型のOCamlセッションである[22]。OCamlのトップレベルは、単にocamlプログラムを実行することで起動する。
$ ocaml
OCaml version 5.4.0
Enter #help;; for help.
#
その後、プロンプト "#" にコードを入力できる。例えば、![]()
OCaml
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/07/06 02:21 UTC 版)
OCamlも bool 型を持ち、値として true と false をとる。 # 1 = 1 ;;- : bool = true
※この「OCaml」の解説は、「ブーリアン型」の解説の一部です。
「OCaml」を含む「ブーリアン型」の記事については、「ブーリアン型」の概要を参照ください。
- OCamlのページへのリンク