Commits

camlspotter committed 977b65e

update

Comments (0)

Files changed (2)

+=================================
+Zippy OCaml チュートリアル
+=================================
+
+OCaml の基礎を抑えた人のために書かれた大雑把なチュートリアル記事集。
+細かい点は書かず、読む人の検索力と考察力に任せることで
+できるだけ多くの話題を取り上げたいと思う。
+
 
 ``let f x = match x with`` でも同様。まあ同じといえば同じだけれども文化的に ``function`` 推奨。
 
-Constructor を curry 化したい
+Variant constructor を curry 化したい
 ======================================
 
 できない
 
-なぜ OCaml のコンストラクタは partial application できないのか
+なぜ OCaml のコンストラクタ(variant constructor)は partial application できないのか
 https://groups.google.com/forum/?fromgroups=#!topic/fa.caml/IOlkCcVBg5Q
 
 CamlP4 で各コンストラクタに対応する curried form な関数を定義することはできる。
 http://www.digipedia.pl/usenet/thread/14273/5152/
-現在も動作するかは不明。 type-conv を使えば簡単に自作できる。
+現在も動作するかは不明。 まあ簡単に自作できる。
 
 標準ライブラリの再帰関数を使ったら Stack overflow 出た
 ======================================================
 例外による再帰関数からの大域脱出は OCaml ではランタイムのペナルティはほとんどないので、 
 ``try with`` を書いてそれでもコードが読みやすければ使って構わない。
 
-特に例外を使うべきなのは Option モナドや Result(Either)モナドで処理を長ーく bind 連結する場合。
-関数を合成しまくるので、どうしてもパフォーマンスが落ちる。例外にしたほうがよい。
+特に例外を使うべきなのは Option モナドや Result(Either)モナドで処理を長ーく ``bind`` (``>>=``) 連結する場合。
+クロージャーを多用するので、どうしてもパフォーマンスが落ちる。例外にしたほうがよい。
 Option モナドの None には Not_found を使えばいいだろう。
 Result のエラーには何か例外を作らなければならないが、例えば、
 ローカルモジュールで作ってみよう(ちょっと長くなる)::
 とはいえ例外に頼りすぎるな
 ==============================================================
 
-例外に頼った再帰からの脱出を使わずとも同等の再帰関数を書くことは(初心者には難しいかもしれないが)全く可能である。
-例外に頼りすぎるのはよくない。::
+例外に頼った再帰からの脱出を使わずとも同等の再帰関数を書くことは
+(初心者には難しいかもしれないが)全く可能である。例外に頼りすぎるのはよくない。::
 
       let exists p list = 
         try 
 カスタム printf の作り方
 ===================================
 
-Printf 系関数におけるフォーマット文字列の型付けは特殊で、そのため普通にフォーマット文字列を受け取り内部でそれを使って ``printf`` を呼び出すような関数は書きづらい::
+Printf 系関数におけるフォーマット文字列の型付けは特殊で、
+そのため普通にフォーマット文字列を受け取り内部でそれを使って
+``printf`` を呼び出すような関数は一見不可能のように見える::
 
     (* 引数列が何個か fmt で決まるので書けないよー *)
     let failwithf fmt 引数列 = failwith (Printf.sprintf fmt 引数列)
             何行でも書けばいいさ
           )
 
+オプショナル引数の使い方
+========================================================================
+
+オプションラベル付き引数とかオプショナル引数とか言われてる奴。
+
+概要
+------------------
+
+``?`` から始まるラベル付き引数はオプショナル。省略できる。
+これは GUI ライブラリのような沢山の引数を持ち、かつそのほとんどの規定値(デフォルト)が決まっている、
+つまり、オプションラベルが無ければ ``t option`` の型を持つ引数が多い場合にとても便利。
+
+省略できると言っても、OCaml は関数型言語であるので、引数が規定値なので省略されているのか、
+それとも partial application で適用されていないのか、区別に難点がある。
+そこで OCaml では、もし、型の上でオプションラベル付き引数より後に来るラベルの無い引数が
+与えられていた場合、その前に来るオプションラベル付き引数は省略され規定値が使われている
+と見なすことにしている。文章で書くと面倒だな。::
+
+    val f : int -> ?foo:bool -> bar:string -> 'a list -> unit
+
+という関数があったとすると、::
+
+    f 3 []
+
+の型は…なんですか? ``bar:string -> unit`` だ。 ``'a list`` というラベルのない引数が
+与えられているので ``?foo:bool`` は省略されているとみなされる。 ``bar:string`` は
+ラベルが付いているがオプショナルではないので残る。一方::
+
+    f 3 ~bar:"hello"
+
+では ``'a list`` が与えられていないので ``?foo:bool`` は省略されておらず、まだ引数が
+与えられていないと考える。なのでこの式の型は ``?foo:bool -> 'a list -> unit`` 。
+
+うっ、難しい?そりゃそうだ、わざと難しい例を出したんだから。
+
+ラベル付き引数の記法
+---------------------
+
+普通に見るのはこんな定義::
+
+    let f x ?(foo=false) ~bar alist = ...
+
+でも、これは次の略記法::
+
+    let f x ?foo:(foo=false) ~bar:bar alist = ...
+
+この記法だと束縛される変数名を変えることができる::
+
+    let f x ?foo:(x=false) ~bar:y alist = ...
+
+とは言え、普通はラベル名と変数名を同じにする略記を使うのがほとんどだろう。
+でもこれを知ってないと内部で使用されていないラベル付き引数を警告なしで書くことができない::
+
+    let f x ?foo:_ ~bar:_ alist = ...
+
+デフォルトの無いオプショナル引数
+---------------------------------
+
+オプショナル引数は ``?(<ラベル>=<デフォルト>)`` と、規定値を書くことが多いが、この規程値
+を書かないこともできる::
+
+    let f x ?foo ~bar alist = match foo with
+      | None -> ...
+      | Some y -> x + y
+
+この際、オプショナル引数の定義内での型は ``τ option`` になる(上だと ``int option``)。
+引数が省略された場合は ``None``、 ``~foo:3`` と書かれた場合は ``Some 3`` が束縛される。
+関数自体の型での引数の型と、関数定義内部での引数の型が異なるのに注目。
+上の関数の型では ``?foo:int`` になっているが、 ``foo`` は定義内部では ``int option`` になる。
+
+
 Ocaml と書く奴は OCaml 使わんでいい
 ============================================