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

Slides:



Advertisements
Similar presentations
2.5 プログラムの構成要素 (1)文字セット ① ASCII ( American Standard Code for Interchange ) JIS コードと同じ ② EBCDIC ( Extended Binary Coded Decimal for Information Code ) 1.
Advertisements

OCamlはじめの一歩 First Step to OCaml 小笠原 啓 (有)ITプランニング
JavaScript プログラミング入門 2006/11/10 神津.
京都大学情報学研究科 通信情報システム専攻 湯淺研究室 M2 平石 拓
ML 演習 第 1 回 佐藤 春旗, 山下 諒蔵, 前田 俊行 May 30, 2006.
プログラミング言語としてのR 情報知能学科 白井 英俊.
ソフトウェア基礎科学 授業資料: 論理関係(logical relations)のお話
2006/11/30 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井 英二郎
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
ISD実習E 2009年6月1日 read関数 read-macro back-quote 文字列のread 課題
12: コマンドライン引数 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
2006/10/19 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井英二郎
条件式 (Conditional Expressions)
~sumii/class/proenb2010/ml4/
の まとめ 2007/04/02 (Mon) / d;id:hzkr
Tokuda Lab. NISHIMURA Taichi
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
ML 演習 第 3 回 新井淳也、中村宇佑、前田俊行 2011/04/26.
プログラミング言語論 第12回 関数型プログラミング 情報工学科 篠埜 功.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング言語入門 手続き型言語としてのJava
PROGRAMMING IN HASKELL
0からわかるF# Part1 中 博俊 F# September 2008 CTP Base.
0からわかるF# Part1 中 博俊 F# September 2008 CTP Base.
PROGRAMMING IN HASKELL
第二回 VB講座 電卓を作ろう.
0からわかるF# Part1 中 博俊 F# September 2008 CTP Base.
プログラミング 4 記憶の割り付け.
プログラミング入門2 第2回 型と演算 条件分岐 篠埜 功.
0からわかるF# Part1 中 博俊 F# September 2008 CTP Base.
PROGRAMMING IN HASKELL
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
コンパイラ演習 第11回 2006/1/19 大山 恵弘 佐藤 秀明.
PHP 概要 担当 岡村耕二 月曜日 2限 平成22年度 情報科学III (理系コア科目・2年生)
0からわかるF# Part1 中 博俊 F# September 2008 CTP Base.
4.リスト,シンボル,文字列.
0からわかるF# Part1 中 博俊 F# September 2008 CTP Base.
情報処理Ⅱ 第2回:2003年10月14日(火).
第5章 計算とプログラム 本章で説明すること ・計算の概観と記述法 ・代表的な計算モデル ・プログラムとプログラム言語.
 型推論3(MLの多相型).
C言語 はじめに 2016年 吉田研究室.
2007/6/12(通信コース)2007/6/13(情報コース) 住井
プログラミング基礎a 第6回 C言語によるプログラミング入門 配列と文字列(その2)
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
PROGRAMMING IN HASKELL
~sumii/class/proenb2010/ml2/
~sumii/class/proenb2009/ml4/
2006/7/18(通信コース)2006/7/26(情報コース) 住井
2006/6/27(通信コース)2006/7/5(情報コース) 住井
情報処理Ⅱ 第7回 2004年11月16日(火).
~sumii/class/proenb2009/ml6/
情報処理Ⅱ 2005年10月28日(金).
PROGRAMMING IN HASKELL
関数型言語の基礎 型なしl計算 型理論 構成的プログラミング GUIにあらわれる関数概念 PBD VL
~sumii/class/proenb2010/ml5/
プログラミング基礎a 第3回 C言語によるプログラミング入門 データ入力
オブジェクト指向言語論 第二回 知能情報学部 新田直也.
コンパイラ 2012年10月11日
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
PROGRAMMING IN HASKELL
情報処理Ⅱ 第2回 2004年10月12日(火).
情報処理Ⅱ 2005年11月25日(金).
プログラミング基礎a 第5回 C言語によるプログラミング入門 配列と文字列
情報処理Ⅱ 小テスト 2005年2月1日(火).
printf・scanf・変数・四則演算
プログラミング演習II 2003年10月29日(第2,3回) 木村巌.
2007/6/26(通信コース)2007/6/27(情報コース) 住井
12: コマンドライン引数 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
Presentation transcript:

(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 n = if n = 1 then 1 else factorial (n - 1) * n

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

並べてみる 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的スタイル」

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

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

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

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

これならOK # 123.0 +. float_of_int 456;; - : float = 579.

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

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

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

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

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

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

左辺のcounterと右辺のcounterは 関数型言語の特徴 # 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

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

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

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

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

レコード型 # type rt = {a : int; b : string};; “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”が定義された

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

ヴァリアント型(2) # type vt2 = Ival of int | Fval of float;; 値つきのヴァリアント型を定義 # 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

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

“Pretty Print List” - 「文字列のリスト」を「文字列」へ変換 パターンマッチング(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”

パターンマッチング(3) ヴァリアントに対するパターンマッチの例 type htmlstr = | UnSafe of string 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) 二つの引数に対する パターンマッチング

モジュール OCaml: Ruby: 『超』乱暴な説明: module Trig = 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) Trig.cos(0) => 1.0 # Trig.cos 0.0;; - : float = 1.

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

Rubyの“collect”イテレータと『ほぼ』同じ(?) 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]

Rubyの“inject”イテレータと『ほぼ』同じ(?) 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

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

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