眠くなくなってきた

お酒飲んだら眠かったのが一周して眠く無くなった
お風呂にお湯を入れている

新しい言語覚えたらとりあえず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

なんだこの統一感のない構文は。

お風呂入ったし寝よう。