This slide is simple Objective Caml Tutorial, used in Axsh at 6/5.
Alternate URL: https://speakerdeck.com/s1061123/ocamllec01-100605110859-phpapp01
7. Objective Camlの親戚一覧ML系列 (Objective Camlと同類)F# (for .Net) http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/default.aspxStandard ML of New Jersey (SML/nj) http://www.smlnj.org/ Alice http://www.ps.uni-saarland.de/alice/SML# http://www.pllab.riec.tohoku.ac.jp/smlsharp/ja/HaskellClosureConcurrent CleanLisp/scheme
40. 関数/条件分岐変数の定義・関数の定義letfoobar = 10;;letfoobar = 15andfoobar2 = 20;;lettestfunc a = print_string “answer is “;print_int (a + 30) ;;lettestfunc a b = a + b;;lettestfun a:int = a;;スコープ付き変数・関数の定義letfoobar = 10 in foobar + 10 ;;名前無し関数(closure)定義 fun a -> a + 10;; let testfunc a b = a + b;; ===== let testfunc = fun a b -> a + b;;これは再代入とは違うので注意!!(新規に領域を作って名前をbindしている)連続した命令は”;”で分ける引数の型は明示的にも宣言可
42. 関数/条件分岐If節の中に複数の命令を入れる場合は注意が必要条件分岐 let testFunc a b = if (a > b) then (print_string “a > b”; a) else (print_string “a =< b”; b)括弧の中を左から評価して最後の値を返す注意:最後以外はunitを返さないとwarning()の代わりにbegin … endでもOK
47. 末尾再帰(tail recursion)の勧めlet rectestFun a = if (a < 1) then 0 else a + testFun (a-1)# testFun 100000000;;Stack overflow during evaluation (looping recursion?).非末尾再帰で一億let rectestFun a b = if (a < 1) then belse testFun (a-1) (b+a)# testFun 1000000000;;- : int = 5000000050000000末尾再帰で十億末尾再帰を思い付く(->再帰脳)は関数型言語の壁の一つOcamlだけではなくHaskell, Closureでも使えるスキルなので是非!
61. ペア複数の型を組み合わせたペアの構造体要素に名前はつかない# (10, 20);;: int * int = (10, 20)# (10, 10.200);;: int * float = (10, 10.2)# (10, "teststr", 30.2);;: int * string * float = (10, "teststr", 30.2)# let pair = (10, "teststr", 30.2);;val pair : int * string * float = (10, "teststr", 30.2)
62. レコードレコード定義cC言語でいう構造体# type pair_of_ints = { a : int; b : int; };;type pair_of_ints = { a : int; b : int; }# {a = 10; b = 20};;- : pair_of_ints = {a = 10; b = 20}# let p = {a = 10; b = 20};;val p : pair_of_ints = {a = 10; b = 20}# p.a;;- : int = 10# let {a=k; b=l} = p;;val k : int = 10val l : int = 20書けば型は推論取るときは”.”を使ってこうやってもOK
63. バリアント関数型言語ならではの構造体イメージとしてはCのenum + uniontypedefstructfoobar_ { enum type_ {TEST_VOID,TEST_INT,TEST_FLOAT,TEST_CHAR } type; union { inti; float d; char c; } val;} foobar;# type foobar = Void | Int of int | Float of float | Char of char | Pair of (int * int);; type foobar = Void | Int of int | Float of float | Char of string | Pair of (int * int)非常にシンプル!
64. バリアント# type foobar = Void | Int of int | Float of float | Char of string | Pair of (int * int);; type foobar = Void | Int of int | Float of float | Char of string | Pair of (int * int)# Void;;- : foobar = Void# Int 20;;- : foobar = Int 20# Pair (20, 20);;- : foobar = Pair (20, 20)使用例: option# None;;- : 'a option = None# Some 10;;- : int option = Some 10
65. パターンマッチデータのパターン(型の構造)で条件分岐が可能!let foobarToStr = function Void -> "void"|Inti-> "Int(" ^ (string_of_inti) ^ ")"| Float f -> "Float(" ^ (string_of_float f) ^ ")"| Char c -> "Char(" ^ c ^ ")" | Pair (a, b) -> "Pair(" ^ (string_of_int a) ^ ", " ^ (string_of_int b) ^ ")";; valfoobarToStr : foobar -> string = <fun>int -> stringの変換:string_of_int文字列の結合: ^# foobarToStr Pair(10,20);;This function is applied to too many arguments,maybe you forgot a `;'# foobarToStr (Pair(10,20));;- : string = "Pair(10, 20)"# foobarToStr Void;;- : string = "void"
66. パターンマッチパターンマッチの方法は3種類# let p = Pair(10,20);;val p : foobar = Pair (10, 20)# let Pair(a,b) = p;;Warning P: this pattern-matching is not exhaustive.Here is an example of a value that is not matched:(Char _|Float _|Int _|Void)val a : int = 10val b : int = 20# let p = (10,20);;val p : int * int = (10, 20)# let (a, b) = p;;val a : int = 10val b : int = 20# let (a, _) = p;;val a : int = 10#単に値を取る場合しかしやや強引ペア等には有効“_”で値を無視
67. パターンマッチ# let foobarToStr a = match a with Void -> "Void" | Int a when a > 100 -> "BigInt" | Int _ -> "Int" | _ -> "Others";;valfoobarToStr : foobar -> string = <fun># foobarToStr (Int 10);;- : string = "Int"# foobarToStr (Int 200);;- : string = "BigInt"# let foob# let foobarToStr a = match a with Void -> "Void" | Int _ -> "Int" | Int a when a > 100 -> "BigInt" | _ -> "Others";;Warning U: this match case is unused.valfoobarToStr : foobar -> string = <fun># foobarToStr (Int 200);;- : string = "Int"When で条件追加比較は上から順番なのでこの場合BigIntが無視
68. 多相型データ・関数ペアの右を返す関数# let getRight(_, a) = a;;valgetRight : 'a * 'b -> 'b = <fun>‘a , ‘b : “型”の変数で’どんな型が来ても構わない’ということ.‘a と’bが同じでも構わない.ただし一回目の’bと二回目の’bは同じ# let getHead (h::t) = h;;Warning P: this pattern-matching is not exhaustive.Here is an example of a value that is not matched:[]valgetHead : 'a list -> 'a = <fun># let getHead l = match l with (h::t) -> Some h | [] -> None;;valgetHead : 'a list -> 'a option = <fun>どんな型のリストも対応する関数
69. 多相型データ・関数多相型レコード# type 'a pairs = { a : 'a ; b : int; };;type 'a pairs = { a : 'a; b : int; }# type 'a tree = None | Node of ('a * 'a tree * 'a tree);;type 'a tree = None | Node of ('a * 'a tree * 'a tree)# Node(10, Node(20, None, None), Node(30, None, None));;- : int tree = Node (10, Node (20, None, None), Node (30, None, None))#多相型バリアントでバイナリツリー102030