1 / 32

(Rubyist のための ) 超音速: ML 入門

(Rubyist のための ) 超音速: ML 入門. 福盛秀雄 http://fukumori.org. Ver.2005.07.30. 準備運動. 階乗の計算. 関数名. 引数. let rec factorial n = if n = 1 then 1 else factorial (n - 1) * n. こんな書き方も. let rec factorial = function | 1 -> 1 | n -> factorial (n - 1) * n. 引数の「パターン」を記述. 並べてみる.

amil
Download Presentation

(Rubyist のための ) 超音速: ML 入門

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. (Rubyistのための)超音速:ML入門 福盛秀雄 http://fukumori.org Ver.2005.07.30

  2. 準備運動 階乗の計算 関数名 引数 let rec factorial n = if n = 1 then 1 else factorial (n - 1) * n

  3. こんな書き方も let rec factorial = function | 1 -> 1 | n -> factorial (n - 1) * n 引数の「パターン」を記述

  4. 並べてみる let rec factorial n = if n = 1 then 1 else factorial (n - 1) * n let rec factorial = function | 1 -> 1 | n -> factorial (n - 1) * n 下の方が「ML的スタイル」

  5. 対話型環境を使ってみる $ ocaml Objective Caml version 3.08.3 #

  6. ふつ~の計算 コロン二つで式の評価 # 123 + 456;; - : int = 579 結果の表示

  7. ふつ~の計算!? 浮動小数点の足し算は +. # 123.0 +. 456.0;; - : float = 579. 普通じゃないよ!

  8. 「暗黙の型変換」? んなものは無い。 浮動小数点演算と 整数演算を混ぜてみる # 123.0 +. 456;; Characters 9-12: 123.0 +. 456;; ^^^ This expression has type int but is here used with type float (当然のように) エラーとなる

  9. これならOK int -> floatの関数 # 123.0 +. float_of_int 456;; - : float = 579.

  10. 変数の定義 let <変数名> = ...で定義 # let a = 1;; val a : int = 1 # let x = “abc”;; val x : string = “abc” 定義された変数の型が表示される

  11. 関数の定義 関数の定義もlet 関数名、引数の順に記述 # let f x = x + 1;; val f : int -> int = <fun> “int -> int”型の関数“f”が定義された

  12. 関数の定義(2) 複数の引数がある場合、 (OCamlでは通常)スペースで区切って並べる # let g x y = x * y;; val g : int -> int -> int = <fun> これをなんと読む? →「二つのintを順に受け取り、intを返す関数」

  13. 「関数」と「変数」の区別は? 本質的には両者の間に明確な区別はない(?)。 関数を別の変数に束縛したり、 別の関数の引数にしたりすることもできる # let f x = x + 1 val f : int -> int = <fun> # let g = f;; val g : int -> int = <fun> # g 1;; - : int = 2 変数gに 関数fを束縛

  14. 無名関数 名前の通り「名前の無い関数」 Rubyのブロックに似ていないこともない {|x| x + 1} Ruby: fun x -> x + 1 OCaml: ちなみにOCamlにて let f x = x + 1 と let f = fun x -> x + 1 は等価

  15. 再帰を示す“rec” 再帰関数の定義には“rec”を付ける # let rec factorial n = if n = 1 then 1 else factorial (n - 1) * n;; val factorial : int -> int = <fun> 付けないと “Unbound value factorial” というエラーとなる

  16. 関数型言語の特徴 # let counter = 0 ;; val counter : int = 0 # let count () = let counter = counter + 1 in counter;; val count : unit -> int = <fun> 変数への「代入」はできない 左辺のcounterと右辺のcounterは 別のもの counterは常に0のため count()の結果は常に1 # count ();; - : int = 1 # count ();; - : int = 1

  17. 関数型言語の特徴(2) • 変数はimmutable→代入はできない • 関数は同じ引数に対して必ず同じ値を返す • ループは書けない(書かない) →再帰を使う • 変数は変更できない →計算の途中経過は引数と   返り値に入れておく

  18. 関数型言語の特徴(3) 「計算の途中経過は引数と 返り値に入れておく」 どうやって実現? 値の定義:強力なデータ型 値の参照:強力なパターンマッチング

  19. リスト(list)とタプル(tuple) リスト ;で区切る # [1;2;3];; - : int list = [1; 2; 3] タプル # (1,2,3);; - : int * int * int = (1, 2, 3)

  20. リストのつくりかた [1;2;3]と書くほかにも… 要素とリストをコロン二つで連結 # 1::[2;3];; - : int list = [1; 2; 3] []は空リスト # 1::2::3::[];; - : int list = [1; 2; 3]

  21. レコード型 “rt”はメンバー “a”,”b”を持つ レコード型“rt”を定義 # type rt = {a : int; b : string};; type rt = { a : int; b : string; } # let rv = {a=1; b="xyz"};; val rv : rt = {a = 1; b = "xyz"} “rt”型の変数“rv”が定義された

  22. ヴァリアント型 “ Cのenum”的な使い方 # type vt = Apple | Banana | Orange;; type vt = Apple | Banana | Orange # let vv = Apple;; val vv : vt = Apple

  23. ヴァリアント型(2) 値つきのヴァリアント型を定義 # type vt2 = Ival of int | Fval of float;; type vt2 = Ival of int | Fval of float # let vvi = Ival 0;; val vvi : vt2 = Ival 0

  24. パターンマッチング 整数値に対するパターンマッチの例 let rec factorial = function | 1 -> 1 | n -> factorial (n - 1) * n

  25. パターンマッチング(2) リストに対するパターンマッチの例 “Pretty Print List” - 「文字列のリスト」を「文字列」へ変換 let rec pp_list = function | [] -> "" | [x] -> x | x :: xs -> x ^ " " ^ pp_list xs xはリストの先頭 xsはリストの残り ^は文字列の連結 # pp_list;; - : string list -> string = <fun> # pp_list [“str1”;”str2”;”str3”];; - : string = “str1 str2 str3”

  26. パターンマッチング(3) ヴァリアントに対するパターンマッチの例 UnSafeはサニタイズされていないHTML文字列 Safeはサニタイズ済みのHTML文字列(のつもり) type htmlstr = | UnSafe of string | Safe of string let concat h1 h2 = match h1, h2 with | UnSafe(s1), UnSafe(s2) -> UnSafe(s1 ^ s2) | UnSafe(s1), Safe(s2) -> UnSafe(s1 ^ s2) | Safe(s1), UnSafe(s2) -> UnSafe(s1 ^ s2) | Safe(s1), Safe(s2) -> Safe(s1 ^ s2) 二つの引数に対する パターンマッチング

  27. モジュール 『超』乱暴な説明: OCaml: Ruby: moduleTrig = struct let pi = 3.141592654 let sin x = ... let cos x = ... end module Trig PI = 3.141592654 def Trig.sin(x) # .. end def Trig.cos(x) # .. end end Trig.cos(0) => 1.0 # Trig.cos 0.0;; - : float = 1.

  28. 標準ライブラリ Listモジュールが 特によく使われるのでとりあえず紹介: 名前の通りリスト関連の 関数が定義されている

  29. List.map Rubyの“collect”イテレータと『ほぼ』同じ(?) Ruby: [1,2,3].collect {|x| x + 1} => [2, 3, 4] OCaml: # List.map (fun x -> x + 1) [1;2;3];; - : int list = [2; 3; 4]

  30. List.fold_left Rubyの“inject”イテレータと『ほぼ』同じ(?) Ruby: [1,2,3].inject(0) {|sum, element| sum + element} => 6 OCaml: # List.fold_left (fun sum element -> sum + element) 0 [1;2;3];; - : int = 6

  31. 命令型処理 “ref”で代入可能な変数(参照型変数)を定義 # let counter = ref 0 ;; val counter : int ref = {contents = 0} # let count () = counter :=!counter + 1; !counter ;; ;でつなげることにより 複数の式を順に評価 • :=で代入(letが無いことに注意) • !を付けると参照型変数の 実際の値が得られる # count ();; - : int = 1 # count ();; - : int = 2

  32. 他にもいろいろありますが… あとは実践あるのみ。 MinCamlのソースコードを 読みに行きましょう。 ということで一旦お開き

More Related