ラベル OCaml の投稿を表示しています。 すべての投稿を表示
ラベル OCaml の投稿を表示しています。 すべての投稿を表示

2011年4月9日土曜日

OCaml Pattern Matching

引きつづきOCaml。今度はパターンマッチング。パターンマッチング自体はその名の通り、与えられた引数の値に応じた値を返す関数を定義する仕組み。

組込み型でのパターンマッチング

(* normal pattern matching *)
let color_to_num = function
    "RED" -> 0
  | "BLUE" -> 1
  | "GREEN" -> 2
  | _ -> -1;;

let num = color_to_num "RED" in
Printf.printf "%d\n" num;;

let num = color_to_num "aardvark" in
Printf.printf "%d\n" num;;

出力

$ ./a.out
0
-1

独自型でのパターンマッチング

(* matching via Sum type*)
type color_t = Red | Blue | Green ;;
let color_t_to_num = function
    Red -> 0
  | Blue -> 1
  | Green -> 2;;

let num = color_t_to_num Blue in
Printf.printf "%d\n" num;;

(* Compile error
let num = color_t_to_num Black in
Printf.printf "%d\n" num;;

let num = color_t_to_num "aardvark" in
Printf.printf "%d\n" num;;
*)

出力

$ ./a.out
1

やっぱ型チェックが厳しいと安心してコードがかけるのがいい。正直Pythonとかはもうあまり書きたくないかも。

パターンマッチングの文法に関しては、let xxxx = function ... という書きかたと let xxxx = match x with ... という書きかたの使いわけが良くわからない。ただ、Oreillyの本で読むかぎりだとfunctionを使う方は単なるシンタックスシュガーっぽい。

2011年4月3日日曜日

Object Oriented OCaml

引きつづきOCaml。OCamlのObject Orientedな部分の仕様が思ってたより膨大で、Thriftが生成したコードが理解できないのでOreillyの本を読みつつサンプルを書いてみる。

oo.ml

class car (name, color)=
  object
      val mutable m_name = name
      val mutable m_color = color
      method get_name = m_name
      method get_color = m_color
      method to_string = m_color ^ " " ^ m_name
  end;;

class flying_car(name, color, flying) =
  object
      inherit car(name, color)
      val mutable m_flying = flying
      method land_car = m_flying <- false
      method fly_car = m_flying <- true
      method to_string =
        let state = if m_flying then "flying" else "not flying" in
        state ^ " " ^ m_color ^ " " ^ m_name
  end;;

let c = new flying_car("Keitora", "black", true) in
let () = c#land_car in
let msg = "I bought a new " ^ c#to_string in
print_endline msg

出力

$ ocamlc oo.ml
$ ./a.out
I bought a new not flying black Keitora

しかしOOな仕様が入ると途端に予約語が増える。ちなみに、最初は関数land_carをlandって名前にしてて謎のコンパイルエラーが発生してた。結局原因はlandという名前の組込み演算子が存在するから。syntax errorってだけじゃなかなか気付かないッスよコンパイラさん。

2011年3月27日日曜日

Konnichiwa OCaml

Goの言語仕様が変わって周辺ライブラリのコンパイルが通らなくなったので、とりあえずGoは放置してOCamlでThriftを試すことにした。その前段階としてOCamlの適当なサンプルでも書いてみる。

OCaml自体は結構前から知ってたけど、使う機会も無いしなんとなく書きかたが気持ちわるかったから敬遠してた。まあこの際だから試そう。

環境のセットアップ

Ubuntuならラクチン。

$ sudo apt-get install ocaml ocaml-mode

hello.ml

(* util functions *)
let concat (x, y) = 
  x ^ " " ^ y;;

(* main function *)
let msg = "konnichiwa" in
let name = "aardvark" in
let con = concat(msg, name) in
    print_endline con ;;

Makefile

コンパイルすると*.cmiというインタフェースの情報を記述したファイルと*.cmoというオブジェクトファイルができるけど、単純に実行バイナリを作るのに必要なのは*.cmoだけっぽい。実際、ソースをコンパイルしたあとにできる*.cmiファイルを消して、そのうえでリンクしても問題無かった。

BIN=hello
SRC=hello.ml
CAMLC=ocamlc
OBJ=$(SRC:.cmo=.ml)

$(BIN): $(OBJ)
 $(CAMLC) -o $(BIN) $(OBJ)

.ml.cmo:
 $(CAMLC) -c $<

clean:
 rm -f *.cm[iox] *~ .*~ #*#
 rm -f $(BIN)

出力

$ make
ocamlc -o hello hello.ml
$ file hello.cmi
hello.cmi: OCaml interface file (.cmi) (Version 011)
$ file hello.cmo
hello.cmo: OCaml object file (.cmo) (Version 007)
$ ./hello
konnichiwa aardvark

末尾のセミコロン二つがちょっと気持ち悪い。