OCaml
オブジェクト指向のML系関数型言語OCaml (Objective Caml) 関連。
最近、Microsoft が .NET Framework に F# として移植 (?) したことで、もしかして火がつくか?! いよいよ、コンパイラ型関数型言語の時代が来るのか?!
Objective Caml 公式サイト
OCamlチュートリアル 有用なチュートリアル
Wiki.OCaml.JP OCamlのWiki
OCaml (私が) 入門
他の人の入門講座ではなく、私自身が入門してゆく過程を書こうという唯我独尊なコーナーです。OCaml のコードと同等な Python コードを出来るだけ書いています。
クラスを書こう
関数よりも先にクラスを書いてみます。
1 class hoge =
2 object
3 method get_val = 10
4 end;;
必ず 10 を返すメソッド get_val を持つクラス hoge を作ったわけです。Python的に書けば
1 class hoge:
2 def get_val(self):
3 return 10
ですね。メソッド get_val の型は、型推論により自動的に int となります。
クラスのインスタンスは
1 let h = new hoge;;
で作ります。Pythonの h = hoge() に相当します。ここでも、h の型は、型推論により hoge になります。メソッド get_val を呼ぶには # を使用して
1 h#get_val
です。Pythonなどの h.get_val() ですね。
クラスは関数と同じく引数を取れるようです。C++などのコンストラクタに相当することが出来るみたいです。
1 class hoge init_val =
2 object
3 method get_val = init_val + 10
4 end;;
5 let h = new hoge 20;;
とすることで
1 h#get_val
が 20 + 10 で 30 になるんですね。
ここでは、init_val が init_val + 10 という式で使われていることから、init_val の型は int と型推論されます。式の中で使わず、
1 class hoge init_val =
2 object
3 method get_val = init_val
4 end;;
とすると、init_val の型を推論できないといって、エラーになってしまいました。そこで、明示的に型を指定してやります。
1 class hoge (init_val : int) =
2 object
3 method get_val = init_val
4 end;;
これで正しく、
1 let h = new hoge 20;;
2 h#get_val;;
で 20 が表示されます。
インスタンス変数
OCaml は関数型言語ですが、変数やインスタンス変数もあるようです。これを使ってみる予定です。
まずは、変更できないインスタンス変数です。関数型言語なのでこちらがデフォルトです。
1 class hoge =
2 object
3 val x = 10
4 method get_x = x
5 end;;
Pythonには定数がないのですが、こんな感じ
1 class hoge:
2 def __init__(self):
3 self.x = 10
4 def get_x(self):
5 return self.x
ジェネリックプログラミング
クラスを使えば、C++のtemplateみたいに、ひとつの関数を別のクラスのインスタンスに適用できます。
1 class hoge =
2 object
3 method get_val = 10
4 end;;
5 class fuga =
6 object
7 method get_val = 20
8 end;;
9 let h = new hoge;;
10 let f = new fuga;;
としておきます。そして、関数を一つ作っておきます。
1 let func x = x#get_val;;
この関数は引数 x のメソッド get_val を呼び出すだけです。この関数には、hoge のインスタンスでも、fuga のインスタンスでも渡せます。
1 func h;; (* 結果は 10 *)
2 func f;; (* 結果は 20 *)
C++ (やD言語) のtemplateと同じように使えるわけです。C# や Java の generics と違って、インターフェイスを用いずとも、引数のメソッドを呼べるようになっています。
では、このときの x の型、というか、func の型はどうなっているのかな? と見てみると…
val func : < get_val : 'a; .. > -> 'a = <fun>
だそうです。これは、
func は「get_val というメソッド (型は 'a) を持つ任意の型」を引数にとり、'a 型の値を返す関数
ってことのようです。'a ってのは、単相型ってやつかな? 上みたいに h を引数として渡した場合、h#get_val が int 型なので、'a は int になるみたいです。
うへぇ。型推論すげえなあ。
継承
となると、あとは継承かな。
