眠くなくなってきた
お酒飲んだら眠かったのが一周して眠く無くなった
お風呂にお湯を入れている
新しい言語覚えたらとりあえずFibだよね。
最初の10個とか取りたいけど http://pauillac.inria.fr/ocaml/htmlman/libref/List.html には「頭10個を取る」って関数はなさそうだ。Pythonのzipに相当するのはcombine。Haskellみたいな無限リストがあって、let recを使える。
あ、リストを2つ取るmap2ってのがあるのか。じゃあcombineいらないな。
# let rec fib = [1; 1; map2 (+) fib (tl fib)];; Error: Unbound value map2 # let rec fib = [1; 1; List.map2 (+) fib (tl fib0)];; Error: Unbound value tl # let rec fib = [1; 1; List.map2 (+) fib (List.tl fib)];; Error: This expression has type int list but an expression was expected of type int # let rec fib = [1; 1]::(List.map2 (+) fib (List.tl fib));; Error: This expression has type int list list but an expression was expected of type int list # let rec fib = 1::1::(List.map2 (+) fib (List.tl fib));; Error: This kind of expression is not allowed as right-hand side of `let rec'
むう、上手くいかない。
とりあえずもう一歩下がってまずは階乗を書くか。
さらに下がってまずインクリメント。
# let inc x = x + 1;; val inc : int -> int = <fun> # inc 2;; - : int = 3 # let inc = (1 +);; Error: Syntax error # let inc = (+) 1;; val inc : int -> int = <fun> # inc 3;; - : int = 4
できた。部分適用の構文がHaskellとちょっと違う。
# let facto n = if (n == 0) then 1 else facto (n - 1);; Error: Unbound value facto # let rec facto n = if (n == 0) then 1 else facto (n - 1);; val facto : int -> int = <fun> # facto 1;; - : int = 1 # facto 3;; - : int = 1 # facto 5;; - : int = 1
あー。
# let rec facto n = if (n == 0) then 1 else n * facto(n - 1);; val facto : int -> int = <fun> # facto(5);; - : int = 120
ケアレスミスね。
末尾再帰に変えるには、と。
# let rec facto_ n answer = if (n == 0) then answer else facto (n - 1) (n * answer);; Error: This function is applied to too many arguments; maybe you forgot a `;' # let rec facto_ n answer = if (n == 0) then answer else facto_ (n - 1) (n * answer);; val facto_ : int -> int -> int = <fun> # let facto n = facto_ n 1;; val facto : int -> int = <fun> # facto 5;; - : int = 120 # facto 6;; - : int = 720
できた。
次はフィボナッチ。
# let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2);; val fib : int -> int = <fun> # fib(5);; - : int = 8
リストで欲しいんだよな。
# let rec count = 1::List.map inc count;; Error: This kind of expression is not allowed as right-hand side of `let rec'
むー、無限リストの作り方がわからん。
# let rec map_take_n f n answer = if (n == 0) then answer else map_take_n f (n - 1) ((f n)::answer);; val map_take_n : (int -> 'a) -> int -> 'a list -> 'a list = <fun> # map_take_n fib 10 [];; - : int list = [1; 2; 3; 5; 8; 13; 21; 34; 55; 89]
フィボナッチできた。次はカウンタオブジェクトを作る。
# type counter = { value : int; push : unit -> int; };; type counter = { value : int; push : unit -> int; } # let c = ref {value = 0};; Error: Some record field labels are undefined: push # let rec c = ref {value = 0; push = fun () -> !c.value};; val c : counter ref = {contents = {value = 0; push = <fun>}} # c.push;; Error: This expression has type counter ref but an expression was expected of type counter # !c.push;; - : unit -> int = <fun> # !c.push ();; - : int = 0
値はとれた。破壊的変更を許すのはmutableをつかって<-で代入するのか。
# let rec c = ref {value = 0; push = fun () -> (!c.value <- !c.value + 1; !c.value)};; val c : counter ref = {contents = {value = 0; push = <fun>}} # !c.push ();; - : int = 1 # !c.push ();; - : int = 2
後はコンストラクタか。
# let make_counter () = let rec c = ref {value = 0; push = fun () -> (!c.value <- !c.value + 1; !c.value)} in c;; val make_counter : unit -> counter ref = <fun> # let c1 = make_counter ();; val c1 : counter ref = {contents = {value = 0; push = <fun>}} # !c1.push ();; - : int = 1 # !c1.push ();; - : int = 2 # let c2 = make_counter ();; val c2 : counter ref = {contents = {value = 0; push = <fun>}} # !c2.push ();; - : int = 1 # !c1.push ();; - : int = 3
うんうん、できてる。
もっと簡単に書くシンタックスシュガーがあるかもしれないが、まあできた。
http://pauillac.inria.fr/ocaml/htmlman/manual005.html
あー、シンタックスシュガーいっぱいある。
# class counter = object val mutable count = 0 method push = (count <- count + 1; count) end;; class counter : object val mutable count : int method push : int end # let c1 = new counter;; val c1 : counter = <obj> # c1#push;; - : int = 1 # c1#push;; - : int = 2
なんだこの統一感のない構文は。
お風呂入ったし寝よう。