Developping application with Objective Caml

最近、表記の本(オンライン)を読みはじめた。

Functional core of Objective CAMLより。

fun a b c d e -> expr

function a -> function b -> function c .... -> expr

と一緒らしい。

あーカリー化ってのは結局そういうことなのかと。

多値nをとる関数でなくて引数を一つとってゴニョゴニョする関数を返すから、結局カリー化ってのは自然に導かれんのかと。

って、ふつうのHaskellにも書いてあったな。

バイナリクロック

どう書くのバイナリクロックの問題をOCamlで

プリントするとこで小一時間悩んだ。で、アレイをハッシュみたいに使ってしまった。

let itobin i =
  if i == 0 then [0]
  else
    let rec itob l i = match i with
        0 -> 1::l
      | 1 -> 1::l
      | _ -> itob ((i mod 2)::l) (i/2)
    in itob [] i
;;

let rec padding l = 
  if (List.length l) < 6 then padding (0::l)
  else l
;;

let format_print l = 
  let d = [|"□";"■"|] in 
  let rec square_print l = match l with
    [] -> print_string "\n"
  | s::r -> print_string d.(s);
      square_print r
    in square_print l
;;


let () = 
  let t = Unix.localtime(Unix.time()) in
  format_print (padding (itobin t.Unix.tm_hour));
  format_print (padding (itobin t.Unix.tm_min))
;;

コンパイルして実行

$ocamlc unix.cma binary_clock.ml -o binary_clock
$ ./binary_clock 
□■□■□■
□■■□□□

OCaml Meeting Tokyo 2009にいった

LLTVにつづき参加。運営の皆様おつかれさまでした。

五十嵐さんのML型推論の光と影の話と、古瀬さんの大駱駝解軆變造概説が特におもしろかった。OCamlのソースも眺める。

  • mzpさんに会った。
  • OCamlは日本酒派が多そう?(私見)
    • OCaml正宗とか語呂が良さげ
  • 開催場所の山上会館と安田講堂を混同していて、かなりロスった。

  • 食べログ

    • 中野大勝軒でつけ麺(29昼)
    • 上野龍門でつけ麺(29夜)
    • 本郷ミュンで鳥カレー(30昼)
    • テツジ?のたいやきとモンシュシュのロールケーキ(30お土産)

OCamlでlablgtk2

labltkではなくてlablgtk2を使ってみる

lablgtk2

let hello () =
  print_endline "Hello World";
  flush stdout

let delete_event ev =
  print_endline "Delete event occurred";
  flush stdout;
  true

let destroy () = GMain.Main.quit ()

let main () =
  let window = GWindow.window ~border_width:10 () in
  window#event#connect#delete ~callback:delete_event;
  window#connect#destroy ~callback:destroy;
  let button = GButton.button ~label:"Hello World" ~packing:window#add () in
  button#connect#clicked ~callback:hello;
  button#connect#clicked ~callback:window#destroy;
  window#show ();
  GMain.Main.main ()

let _ = main ()

「文字コード超研究」を読んだ

utf8の話が参考になった。

ProductName 文字コード超研究
深沢 千尋
ラトルズ / ¥ 3,129 ()
在庫あり。

ついでにExtlibのUTF8のソースも読んで理解を深めた。

# #require "extlib";;
/opt/local/lib/ocaml/site-lib/extlib: added to search path
/opt/local/lib/ocaml/site-lib/extlib/extLib.cma: loaded
# open UTF8;;
# let moji2 = "\xc3\x86";;
val moji2 : string = "\195\134"
# print_string moji2;; 
Æ- : unit = ()

OCamlでtake

今日のOCaml

Ocamlはlistでtakeが使えん。どうもextlibを使う必要があるらしい。

# #require "extlib";;
/opt/local/lib/ocaml/site-lib/extlib: added to search path
/opt/local/lib/ocaml/site-lib/extlib/extLib.cma: loaded
# open ExtList.List;;
# let a = [1;2;3;4;5;6;7;8;9;0];;
val a : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 0]
# take 3 a;;
- : int list = [1; 2; 3]

OCamlのUnknow directive

ocamlnetのhttp clientのサンプルを実行しようとしたら

#require "netclient";;
open Http_client.Convenience;;
let get_and_print url =
  let s = http_get url in
  print_string s;
  flush stdout
;;

このrequireでエラー

# #require "netclient";;
Unknown directive `require'.

解決方法

sudo port install caml-findlib

で、.ocamlinitに

#use "topfind"

と書いておく。

モジュールっていうかライブラリ周りの流儀がまだよく分かってない。

ocamlとocamlcとload

例えば、こんな感じでloadして、

#load "unix.cma";;

let file = "/Users/kzfm/OCaml/kaeru.ml"

let () =
  let proc = Unix.open_process_in ("wc -l < " ^ file) in
  let count = input_line proc in
  ignore (Unix.close_process_in proc);
  print_string count;;

実行すると

$ ocaml wc.ml
      28

一方、コンパイルしようとすると

$ ocamlc unix.cma wc.ml
File "wc.ml", line 1, characters 0-1:
Error: Syntax error

エラーがでるが、#loadという行を除くときちんとコンパイルできる。

コンパイルしたい場合は毎度#loadっていう行を削除しないといけないのかな。

今日のOCaml

文法事項 -OCaml-より

let rec fact = function
      0 -> 1
    | n -> n * fact (n-1);;

これは、

let rec fact' =
  (fun x -> match x with
    0 -> 1
  | n -> n * fact' (n-1));;

さて、Objective Caml入門

同じ名前の関数を宣言することで隠すのが,Objective Camlプログラミングの常套テクニックとして使われる.

とあって、

# let rec fact (n, res) = if n = 1 then res else fact (n - 1, res * n);;
val fact : int * int -> int = <fun>
# let fact n = fact (n, 1);;
val fact : int -> int = <fun>

あーc++のオーバーロードみたいなもんか?と思ったんだけどどうも違うらしい。

# let f (x,y) = x + y;;
val f : int * int -> int = <fun>
# let f x y = x +. y;;
val f : float -> float -> float = <fun>

こんなのは動かない。

OCamlとlambda

後者は構文糖衣?

# let f = fun x -> x * x
val f : int -> int = <fun>
# let g x = x * x;;
val g : int -> int = <fun>

ここまでやれる

# ( * ) 4 4;;

Common Lispだとこうかな

(setq f (lambda (x) (* x x)))
(funcall f 4)

(defun g (x) (* x x))
(g 4)