OCaml熱さいかい(三日坊主になりませんように)
大学の図書館でThe Little Schemerを探したら貸し出し中だったので、なんかおもしれー本ねーかなーと探していたらThe Little MLerなる本を見つけた。おもしろそうなので借りた。読んだ。おもしろい。ちんたら読んでるので前の方しかまだ読んでないけど、パターンマッチパターンマッチパターンマッチ。
そんなわけで、よしMLで遊ぼうと思った。で、StandardMLとOCamlのどっちにしようかなと迷ったけれども、http://www.mpi-sws.mpg.de/~rossberg/sml-vs-ocaml.html を見て、OCamlはなんでもletで束縛するのが好みで、逆にSMLは~1.0、andalso、orelseみたいなのが嫌かもと思ったのでOCamlに。
The Little MLerに出てくるプログラム片はこんなの。
# fact 5;; - : int = 120 # type shish_kebab = Skewer | Onion of shish_kebab | Lamb of shish_kebab | Tomato of shish_kebab;; type shish_kebab = Skewer | Onion of shish_kebab | Lamb of shish_kebab | Tomato of shish_kebab # Skewer;; - : shish_kebab = Skewer # Lamb(Skewer);; - : shish_kebab = Lamb Skewer # let rec only_onions = function Skewer -> true | Onion(x) -> only_onions(x) | Lamb(x) -> false | Tomato(x) -> false;; val only_onions : shish_kebab -> bool = <fun> # only_onions(Lamb(Skewer));; - : bool = false # only_onions(Onion(Lamb(Onion(Skewer))));; - : bool = false # only_onions(Onion(Onion(Onion(Skewer))));; - : bool = true
本に載ってるのはSMLのコードですけど。
パターンマッチ使っていつぞ書いたfactとか書くとこうか。
# let rec fact = function 0 -> 1 | n -> n*(fact (n-1));; val fact : int -> int = <fun> # fact 10;; - : int = 3628800
リファレンス。http://caml.inria.fr/pub/docs/manual-ocaml/index.html
日本語もあった。http://ocaml.jp/archive/ocaml-manual-3.06-ja/
SICPっぽくすると
末尾再帰で。こうか。途中の(0,a)とかはたぶんtupleとかいうやつ。
# let fact x = let rec f = function (0,a) -> a | (x,a) -> f(x-1,a*x) in f(x,1);; val fact : int -> int = <fun> # fact 10;; - : int = 3628800
リストを逆順に並べるとか。
# let rec my_reverse = function [] -> [] | hd::tl -> (my_reverse tl) @ [hd];; val my_reverse : 'a list -> 'a list = <fun> # my_reverse [1;2;3;4;];; - : int list = [4; 3; 2; 1] # let my_reverse ls = let rec rev = function ([],rls) -> rls | (hd::tl,rls) -> rev(tl, [hd]@rls) in rev (ls,[]);; val my_reverse : 'a list -> 'a list = <fun> # my_reverse [1;2;3;4];; - : int list = [4; 3; 2; 1]
ふむ。パタンマッチいいなこれは確かに。hd::tlはcar::cdrと書くとLisperに優しいですね。