SlideShare a Scribd company logo
言語処理系入門
第4回:関数の実装
2009 年 11 月 13 日(金)
服部 健太
2009/11/13 言語処理系入門 4 2
関数
 我々の言語に関数を追加したい
# let double x = x + x in
double (3+4);
==> 14
# let abs n =
if n >= 0 then n else –n
in
abs (-123)
==> 123
# let square_add a b = a * a + b * b in
square_add 5 2;
==> 29
2009/11/13 言語処理系入門 4 3
第一級市民 (first class object) とし
ての関数も扱いたい
 高階関数
 …関数を返す関数,関数を引数にとる関数,
 例:
let twice f x = f (f x);
let make_adder x =
   let adder y = x + y
in adder;
 匿名関数
 関数をいちいち定義せずにその場で作れる
twice (fn x -> x + x) 5;
(fn f x -> f x) (fn x -> x * x) 3;
2009/11/13 言語処理系入門 4 4
クロージャ
 関数を表すオブジェクト
 <仮引数名,関数本体のコード,環境>の3つ組
み
 環境は関数が生成される時点のもの
 関数適用時,仮引数を実引数の値で対応させ
たエントリが環境に追加され,その新しい環
境のもとで,関数本体の式が評価される
 例 :
let y = -9 in
fn x = x + y
x
x + y
変数 値
y -9
2009/11/13 言語処理系入門 4 5
クロージャが不要な場合
 C 言語の場合
 関数の入れ子定義はできない.
 関数ポインタはある
⇒ 単なる関数の開始アドレス
 Pascal 言語の場合
 関数を返す関数は定義できない
 関数の入れ子定義はできる
⇒ アクセスリンクを辿って,外側の変数にアクセス
可能
2009/11/13 言語処理系入門 4 6
形式的意味
 以下のように ( 抽象 ) 構文を拡張
E ::= E E 関数適用
V ::= fn x -> E 関数生成
 値
v Val = Clos(x,E,ρ)∈
),,(| ρρ ExClosEx ⇓>− -fn
vEE
vEvxvEExClosE
⇓−
⇓−±⇓−⇓−
21
21
|
'|}''{'|)',','(|
ρ
ρρρρ 
2009/11/13 言語処理系入門 4 7
関数の実装
 抽象構文の拡張( syntax.ml )
let rec expr = …
| AppExpr of expr * expr
and value = …
| FunVal of Symbol.t * expr
 評価器の拡張 (eval.ml)
let rec eval_expr env e = match e with …
| AppExpr(e1,e2) -> clos_apply env
(Value.get_clos (eval_expr env e1)) e2
and eval_value env v = match v with …
| FunVal(x,e) -> Value.Clos(env,x,e)
and clos_apply env (env',x,e') e =
let xvs = eval_binds env [x,e] in
eval_expr (Env.extend env' xvs) e'
2009/11/13 言語処理系入門 4 8
Syntax sugar
 複数の引数を持つ関数
[[fn x1 x2 … xn -> E]]⇒
fn x1 -> (fn x2 -> … (fn xn -> [[E]])…)
 let による関数定義
[[let f x1 … xn = E]]⇒
  let f = [[fn x1 … xn -> [[E]] ]]
 関数適用
[[E1 E2 … En]]⇒
(…(([[E1]] [[E2]]) [[E3]]) … [[En]])
カリー化という
2009/11/13 言語処理系入門 4 9
再帰的定義のための let rec 形式
 再帰関数を定義するには,普通に let を使っ
てもダメ
let fact =
fn n -> if n == 0
then 1 else n * fact(n – 1)
in fact 5
 let rec 形式を導入する
 = の右辺式を拡張した環境の下で評価する
},,{'
|
|'1for|'
11
11
nn
nn
ii
vxvx
vEExEx
vEnivE


±=
⇓==−
⇓−≤≤⇓−
ρρ
ρ
ρρ
inandreclet
2009/11/13 言語処理系入門 4 10
let rec の実装
 eval.ml
let rec eval_expr env e = match e with …
| LetRecExpr(ds,e1) ->
let env' = eval_rec_decls env ds
in eval_expr env' e1
…
and eval_rec_decls env ds =
let env' =
Env.extend env
(List.map (fun (x,e) ->
x,Value.UndefinedObj) ds)
in
let xvs = eval_binds env' ds in
Env.updates env' xvs; env'
仮の値で環境
を拡張
後で正式な値
で環境を更新
2009/11/13 言語処理系入門 4 11
let rec を使わない再帰関数定義
 以下のように fix オペレータ(関数)を定義する
let fix f =
(fn x -> f (fn y-> x x y))
(fn x -> f (fn y-> x x y))
 例: factorial 関数の定義
# let factorial =
fix (fn fct n ->
if n == 0 then 1
else n * fct (n – 1));
# factorial 5;
==> 60
 演習問題:
 fix オペレータが動くことを確認し,なぜ再帰を生み出すのか
考えよ
Syntax sugar(2)
 begin ~ end 文の実装
[[begin E1; E2; … ; En end]]⇒
let _ = [[E1]] in let _ = [[E2]]in … in [[En]]
 while 文の実装
[[while E1 do E2]]⇒
let rec loop x =
if x then begin [[E2]]; loop [[E1]]end
in
loop [[E1]]
2009/11/13 言語処理系入門 4 12
loop, x はフレッシュな
変数
( E1,E2 中に出現しな
い)
参照呼び出し( Call-by-
Reference )
 swap 関数を定義したい
# let x = 3 and y = 4;
# swap x y;
 x ==> 4, y ==> 3 となる
 以下のように定義してもうまくいかない
let swap x y =
let temp = x in
begin x := y; y := temp end;
 引数 x と y は関数呼び出し時にコピーされてしまう
2009/11/13 言語処理系入門 4 13
)',(|,
)',(|},,{},,,{
1for),(|,
22110
111
1
SvEExExExS
SvElxlxvlvlS
niSvES
nn
nnnnin
iiii
⇓===−
⇓−±
≤≤⇓−−
inandandlet 

ρ
ρ
ρ niSDOMl ni ≤≤∉ 1eachfor)(if
参照呼び出しのセマンティクス
 右辺式が変数ならば,コピーしない
 環境の実装
 環境に格納する値が,直接的な値
( DirectObject )か参照値( IndirectObject )か
を区別できるようにする
2009/11/13 言語処理系入門 4 14
)',(|,
)',(|}{,
SvEyxS
SvElxS
⇓=−
⇓−±
inletρ
ρ 
)( ly =ρ
Direct Int 5
Indirect
x
y
参照呼び出しの実装
 参照はがし
let deref = function
| Value.DirectObj v -> v
| Value.IndirectObj loc -> (
match Loc.get_val loc with
| Value.DirectObj v -> v
| Value.IndirectObj _ ->
           raise Invalid_reference_error
| Value.UndefinedObj x ->
           raise (Undefined_variable_error x)
)
   | Value.UndefinedObj x ->
      raise (Undefined_variable_error x)
 評価器
let rec eval_expr env e = match e with …
| VarExpr x -> deref (Env.lookup env x)
2009/11/13 言語処理系入門 4 15
参照呼び出しの実装(2)
 参照先設定
let setref loc v =
let loc' =
match Loc.get_val loc with
| Value.IndirectObj loc'' -> loc''
| _ -> loc
in
Loc.set_val loc' (Value.DirectObj v)
 評価器 (eval_expr)
| AsgnExpr(x,e1) ->
let v = eval_expr env e1 in
setref (get_var_loc env x) v; v
2009/11/13 言語処理系入門 4 16
参照呼び出しの実装(3)
 変数束縛の処理
and eval_bind env (x,e) =
x,(match e with
| VarExpr x' ->
let loc = get_var_loc env x' in (
match Loc.get_val loc with
| Value.IndirectObj loc' ->
Value.IndirectObj loc'
| _ -> Value.IndirectObj loc
)
| _ -> Value.DirectObj(eval_expr env e)
)
2009/11/13 言語処理系入門 4 17
名前呼び出し( Call by Name )
 関数呼び出し時に,引数を評価しない.
 関数の中で実際に引数を使うときに評価する
 値呼び出しと名前呼び出しとでの重要な動作の
違い
# let rec loop x = loop x;
# let do_nothing x = 0;
# do_nothing (loop 0);
???
 値呼び出しだと無限ループするが,名前呼び出
しだと停止する
 実用的な使い途として無限ストリームの実装に使える
2009/11/13 言語処理系入門 4 18
無限ストリームの例
// cons の手続き的な実装
let cons ?x ?y = fn m -> if m then x else y;
let car b = b true;
let cdr b = b false;
// 無限ストリームの実装
let generator n = cons n (generator (n + 1));
# let stream = generator 0;
# car stream;
==> 0
# car (cdr stream);
==> 1
# car (cdr (cdr stream));
==> 2
… 以下メモリの続く限り
2009/11/13 言語処理系入門 4 19
名前呼び出しの実装
 関数適用のとき,引数を評価せず,かわりにサ
ンクオブジェクト(引数なしの関数)を作成し
,束縛する.
(* サンクオブジェクトを作成する *)
and thunk env e =
   Value.ThunkObj
   (fun () -> eval_expr env e)
 変数を評価するときに,対象がサンクオブジェ
クトの場合は,サンクオブジェクトを呼び出し
て結果を得る.
 サンプルプログラムでは deref 関数内で処理
let deref = function
…
| Value.ThunkObj t -> t()2009/11/13 言語処理系入門 4 20
演習課題
 今週のサンプルプログラムを動かしてみよ
 サンプルプログラムでは,値呼び出し,名前呼び出し参照呼び
出しを実装してある.
 値呼び出しの場合
 let x = E, let f x = E
 参照呼び出しの場合
 let &x = E, let f &x = E のように変数名の前に & をつける
 名前呼び出しの場合
 let ?x = E, let f ?x = E のように変数名の前に ? をつける
 以下の挙動を確認せよ
 let rec x = x;
 let rec &x = x;
 let rec ?x = x;
 上の結果の違いをそれぞれ説明せよ
2009/11/13 言語処理系入門 4 21
2009/11/13 言語処理系入門 4 22
次回予定
 日時:
 2009 年 11 月 20 日(金) 17 : 00 - 18 : 30
 場所:
 LB2 3F/A 会議室
 内容:
 いろいろなデータ型の扱い
 タグ付きレコード,文字列 etc.

More Related Content

What's hot

Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpSwift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Tomohiro Kumagai
 
Swift らしい表現を目指そう #eventdots
Swift らしい表現を目指そう #eventdotsSwift らしい表現を目指そう #eventdots
Swift らしい表現を目指そう #eventdots
Tomohiro Kumagai
 
プロトコル指向 - 夢と現実の狭間 #cswift
プロトコル指向 - 夢と現実の狭間 #cswiftプロトコル指向 - 夢と現実の狭間 #cswift
プロトコル指向 - 夢と現実の狭間 #cswift
Tomohiro Kumagai
 
F#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングF#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングsatoshimurakumo
 
X hago2 shortcoding 20110827
X hago2 shortcoding 20110827X hago2 shortcoding 20110827
X hago2 shortcoding 20110827
uskey512
 
apg4b 4.05 ポインタ
apg4b 4.05 ポインタapg4b 4.05 ポインタ
apg4b 4.05 ポインタ
APG4b
 
ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】株式会社ランチェスター
 
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsapSwift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Tomohiro Kumagai
 
F#のすすめ
F#のすすめF#のすすめ
F#のすすめ
Hiromu Sasaki
 
スクリプトで文字コード変換
スクリプトで文字コード変換スクリプトで文字コード変換
スクリプトで文字コード変換
1000 VICKY
 
Mock and patch
Mock and patchMock and patch
Mock and patch
Toru Furukawa
 
プログラムの実行順序
プログラムの実行順序プログラムの実行順序
プログラムの実行順序
APG4b
 
repマクロ
repマクロrepマクロ
repマクロ
APG4b
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
Ryo Suzuki
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
Ouka Yuka
 
JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文
Appresso Engineering Team
 
Applicative functor
Applicative functorApplicative functor
Applicative functor
Yuichi Adachi
 
while文
while文while文
while文
APG4b
 

What's hot (20)

Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorpSwift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
 
Swift らしい表現を目指そう #eventdots
Swift らしい表現を目指そう #eventdotsSwift らしい表現を目指そう #eventdots
Swift らしい表現を目指そう #eventdots
 
プロトコル指向 - 夢と現実の狭間 #cswift
プロトコル指向 - 夢と現実の狭間 #cswiftプロトコル指向 - 夢と現実の狭間 #cswift
プロトコル指向 - 夢と現実の狭間 #cswift
 
F#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングF#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミング
 
C++14 Overview
C++14 OverviewC++14 Overview
C++14 Overview
 
X hago2 shortcoding 20110827
X hago2 shortcoding 20110827X hago2 shortcoding 20110827
X hago2 shortcoding 20110827
 
apg4b 4.05 ポインタ
apg4b 4.05 ポインタapg4b 4.05 ポインタ
apg4b 4.05 ポインタ
 
ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】
 
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsapSwift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
 
F#のすすめ
F#のすすめF#のすすめ
F#のすすめ
 
スクリプトで文字コード変換
スクリプトで文字コード変換スクリプトで文字コード変換
スクリプトで文字コード変換
 
Mock and patch
Mock and patchMock and patch
Mock and patch
 
プログラムの実行順序
プログラムの実行順序プログラムの実行順序
プログラムの実行順序
 
repマクロ
repマクロrepマクロ
repマクロ
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
 
C++11
C++11C++11
C++11
 
JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文
 
Applicative functor
Applicative functorApplicative functor
Applicative functor
 
while文
while文while文
while文
 

Similar to 言語処理系入門4

言語処理系入門3
言語処理系入門3言語処理系入門3
言語処理系入門3
Kenta Hattori
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
Masao Kato
 
F#によるFunctional Programming入門
F#によるFunctional Programming入門F#によるFunctional Programming入門
F#によるFunctional Programming入門
bleis tift
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
bleis tift
 
Swift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftSwift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswift
Tomohiro Kumagai
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
Susisu
 
すごいHaskell読書会#1 in 大阪
すごいHaskell読書会#1 in 大阪すごいHaskell読書会#1 in 大阪
すごいHaskell読書会#1 in 大阪yashigani
 
Introduction Xtend
Introduction XtendIntroduction Xtend
Introduction Xtend
Hideki Kishida
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
Shinichi Kozake
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
masatora atarashi
 
言語処理系入門€10
言語処理系入門€10言語処理系入門€10
言語処理系入門€10
Kenta Hattori
 
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーNode.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
mganeko
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
Ransui Iso
 
pecl-AOPの紹介
pecl-AOPの紹介pecl-AOPの紹介
pecl-AOPの紹介
Hiraku Nakano
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPI
Daisuke Igarashi
 
ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】株式会社ランチェスター
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)
Masahiro Hayashi
 
「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04
Minoru Chikamune
 
普通のプログラミング言語R
普通のプログラミング言語R普通のプログラミング言語R
普通のプログラミング言語R
Shuyo Nakatani
 
Testman
TestmanTestman

Similar to 言語処理系入門4 (20)

言語処理系入門3
言語処理系入門3言語処理系入門3
言語処理系入門3
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
F#によるFunctional Programming入門
F#によるFunctional Programming入門F#によるFunctional Programming入門
F#によるFunctional Programming入門
 
yieldとreturnの話
yieldとreturnの話yieldとreturnの話
yieldとreturnの話
 
Swift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftSwift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswift
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
すごいHaskell読書会#1 in 大阪
すごいHaskell読書会#1 in 大阪すごいHaskell読書会#1 in 大阪
すごいHaskell読書会#1 in 大阪
 
Introduction Xtend
Introduction XtendIntroduction Xtend
Introduction Xtend
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
言語処理系入門€10
言語処理系入門€10言語処理系入門€10
言語処理系入門€10
 
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーNode.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
 
pecl-AOPの紹介
pecl-AOPの紹介pecl-AOPの紹介
pecl-AOPの紹介
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPI
 
ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)
 
「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04「Lispインタープリター」勉強会 2014.12.04
「Lispインタープリター」勉強会 2014.12.04
 
普通のプログラミング言語R
普通のプログラミング言語R普通のプログラミング言語R
普通のプログラミング言語R
 
Testman
TestmanTestman
Testman
 

More from Kenta Hattori

オブジェクト指向入門2
オブジェクト指向入門2オブジェクト指向入門2
オブジェクト指向入門2
Kenta Hattori
 
オブジェクト指向入門1
オブジェクト指向入門1オブジェクト指向入門1
オブジェクト指向入門1
Kenta Hattori
 
オブジェクト指向入門10
オブジェクト指向入門10オブジェクト指向入門10
オブジェクト指向入門10
Kenta Hattori
 
オブジェクト指向入門9
オブジェクト指向入門9オブジェクト指向入門9
オブジェクト指向入門9
Kenta Hattori
 
オブジェクト指向入門8
オブジェクト指向入門8オブジェクト指向入門8
オブジェクト指向入門8
Kenta Hattori
 
オブジェクト指向入門7
オブジェクト指向入門7オブジェクト指向入門7
オブジェクト指向入門7
Kenta Hattori
 
オブジェクト指向入門6
オブジェクト指向入門6オブジェクト指向入門6
オブジェクト指向入門6
Kenta Hattori
 
オブジェクト指向入門5
オブジェクト指向入門5オブジェクト指向入門5
オブジェクト指向入門5
Kenta Hattori
 
オブジェクト指向入門4
オブジェクト指向入門4オブジェクト指向入門4
オブジェクト指向入門4
Kenta Hattori
 
オブジェクト指向入門3
オブジェクト指向入門3オブジェクト指向入門3
オブジェクト指向入門3
Kenta Hattori
 
ソフトウェア・テスト入門2
ソフトウェア・テスト入門2ソフトウェア・テスト入門2
ソフトウェア・テスト入門2
Kenta Hattori
 
ソフトウェア・テスト入門1
ソフトウェア・テスト入門1ソフトウェア・テスト入門1
ソフトウェア・テスト入門1
Kenta Hattori
 
ソフトウェア・テスト入門8
ソフトウェア・テスト入門8ソフトウェア・テスト入門8
ソフトウェア・テスト入門8
Kenta Hattori
 
ソフトウェア・テスト入門7
ソフトウェア・テスト入門7ソフトウェア・テスト入門7
ソフトウェア・テスト入門7
Kenta Hattori
 
ソフトウェア・テスト入門6
ソフトウェア・テスト入門6ソフトウェア・テスト入門6
ソフトウェア・テスト入門6
Kenta Hattori
 
ソフトウェア・テスト入門5
ソフトウェア・テスト入門5ソフトウェア・テスト入門5
ソフトウェア・テスト入門5
Kenta Hattori
 
ソフトウェア・テスト入門4
ソフトウェア・テスト入門4ソフトウェア・テスト入門4
ソフトウェア・テスト入門4
Kenta Hattori
 
ソフトウェア・テスト入門3
ソフトウェア・テスト入門3ソフトウェア・テスト入門3
ソフトウェア・テスト入門3
Kenta Hattori
 
アルゴリズムとデータ構造15
アルゴリズムとデータ構造15アルゴリズムとデータ構造15
アルゴリズムとデータ構造15
Kenta Hattori
 
アルゴリズムとデータ構造14
アルゴリズムとデータ構造14アルゴリズムとデータ構造14
アルゴリズムとデータ構造14
Kenta Hattori
 

More from Kenta Hattori (20)

オブジェクト指向入門2
オブジェクト指向入門2オブジェクト指向入門2
オブジェクト指向入門2
 
オブジェクト指向入門1
オブジェクト指向入門1オブジェクト指向入門1
オブジェクト指向入門1
 
オブジェクト指向入門10
オブジェクト指向入門10オブジェクト指向入門10
オブジェクト指向入門10
 
オブジェクト指向入門9
オブジェクト指向入門9オブジェクト指向入門9
オブジェクト指向入門9
 
オブジェクト指向入門8
オブジェクト指向入門8オブジェクト指向入門8
オブジェクト指向入門8
 
オブジェクト指向入門7
オブジェクト指向入門7オブジェクト指向入門7
オブジェクト指向入門7
 
オブジェクト指向入門6
オブジェクト指向入門6オブジェクト指向入門6
オブジェクト指向入門6
 
オブジェクト指向入門5
オブジェクト指向入門5オブジェクト指向入門5
オブジェクト指向入門5
 
オブジェクト指向入門4
オブジェクト指向入門4オブジェクト指向入門4
オブジェクト指向入門4
 
オブジェクト指向入門3
オブジェクト指向入門3オブジェクト指向入門3
オブジェクト指向入門3
 
ソフトウェア・テスト入門2
ソフトウェア・テスト入門2ソフトウェア・テスト入門2
ソフトウェア・テスト入門2
 
ソフトウェア・テスト入門1
ソフトウェア・テスト入門1ソフトウェア・テスト入門1
ソフトウェア・テスト入門1
 
ソフトウェア・テスト入門8
ソフトウェア・テスト入門8ソフトウェア・テスト入門8
ソフトウェア・テスト入門8
 
ソフトウェア・テスト入門7
ソフトウェア・テスト入門7ソフトウェア・テスト入門7
ソフトウェア・テスト入門7
 
ソフトウェア・テスト入門6
ソフトウェア・テスト入門6ソフトウェア・テスト入門6
ソフトウェア・テスト入門6
 
ソフトウェア・テスト入門5
ソフトウェア・テスト入門5ソフトウェア・テスト入門5
ソフトウェア・テスト入門5
 
ソフトウェア・テスト入門4
ソフトウェア・テスト入門4ソフトウェア・テスト入門4
ソフトウェア・テスト入門4
 
ソフトウェア・テスト入門3
ソフトウェア・テスト入門3ソフトウェア・テスト入門3
ソフトウェア・テスト入門3
 
アルゴリズムとデータ構造15
アルゴリズムとデータ構造15アルゴリズムとデータ構造15
アルゴリズムとデータ構造15
 
アルゴリズムとデータ構造14
アルゴリズムとデータ構造14アルゴリズムとデータ構造14
アルゴリズムとデータ構造14
 

Recently uploaded

FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)
fisuda
 
BitVisor Summit 10「3. Thin Hypervisor on AArch64」
BitVisor Summit 10「3. Thin Hypervisor on AArch64」BitVisor Summit 10「3. Thin Hypervisor on AArch64」
BitVisor Summit 10「3. Thin Hypervisor on AArch64」
BitVisor
 
NIST Cybersecurity Framework 2.0の変更点整理をしよう
NIST Cybersecurity Framework 2.0の変更点整理をしようNIST Cybersecurity Framework 2.0の変更点整理をしよう
NIST Cybersecurity Framework 2.0の変更点整理をしよう
You&I
 
アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)
アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)
アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)
You&I
 
受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf
受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf
受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf
ooishi1
 
Grokking Simplicity探訪
Grokking Simplicity探訪Grokking Simplicity探訪
Grokking Simplicity探訪
Yoshitaka Kawashima
 
CO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdf
CO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdfCO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdf
CO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdf
yamamotominami
 

Recently uploaded (7)

FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 4.0.0対応)
 
BitVisor Summit 10「3. Thin Hypervisor on AArch64」
BitVisor Summit 10「3. Thin Hypervisor on AArch64」BitVisor Summit 10「3. Thin Hypervisor on AArch64」
BitVisor Summit 10「3. Thin Hypervisor on AArch64」
 
NIST Cybersecurity Framework 2.0の変更点整理をしよう
NIST Cybersecurity Framework 2.0の変更点整理をしようNIST Cybersecurity Framework 2.0の変更点整理をしよう
NIST Cybersecurity Framework 2.0の変更点整理をしよう
 
アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)
アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)
アジャイルの30年(Tree Decades of Agileというブログ記事に関する要約)
 
受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf
受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf
受発注バスターズ説明資料  株式会社batton Saleshub掲載用.pdf
 
Grokking Simplicity探訪
Grokking Simplicity探訪Grokking Simplicity探訪
Grokking Simplicity探訪
 
CO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdf
CO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdfCO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdf
CO2排出量見える化・削減・報告クラウド「アスエネ」サービス紹介_Saleshub.pdf
 

言語処理系入門4

  • 2. 2009/11/13 言語処理系入門 4 2 関数  我々の言語に関数を追加したい # let double x = x + x in double (3+4); ==> 14 # let abs n = if n >= 0 then n else –n in abs (-123) ==> 123 # let square_add a b = a * a + b * b in square_add 5 2; ==> 29
  • 3. 2009/11/13 言語処理系入門 4 3 第一級市民 (first class object) とし ての関数も扱いたい  高階関数  …関数を返す関数,関数を引数にとる関数,  例: let twice f x = f (f x); let make_adder x =    let adder y = x + y in adder;  匿名関数  関数をいちいち定義せずにその場で作れる twice (fn x -> x + x) 5; (fn f x -> f x) (fn x -> x * x) 3;
  • 4. 2009/11/13 言語処理系入門 4 4 クロージャ  関数を表すオブジェクト  <仮引数名,関数本体のコード,環境>の3つ組 み  環境は関数が生成される時点のもの  関数適用時,仮引数を実引数の値で対応させ たエントリが環境に追加され,その新しい環 境のもとで,関数本体の式が評価される  例 : let y = -9 in fn x = x + y x x + y 変数 値 y -9
  • 5. 2009/11/13 言語処理系入門 4 5 クロージャが不要な場合  C 言語の場合  関数の入れ子定義はできない.  関数ポインタはある ⇒ 単なる関数の開始アドレス  Pascal 言語の場合  関数を返す関数は定義できない  関数の入れ子定義はできる ⇒ アクセスリンクを辿って,外側の変数にアクセス 可能
  • 6. 2009/11/13 言語処理系入門 4 6 形式的意味  以下のように ( 抽象 ) 構文を拡張 E ::= E E 関数適用 V ::= fn x -> E 関数生成  値 v Val = Clos(x,E,ρ)∈ ),,(| ρρ ExClosEx ⇓>− -fn vEE vEvxvEExClosE ⇓− ⇓−±⇓−⇓− 21 21 | '|}''{'|)',','(| ρ ρρρρ 
  • 7. 2009/11/13 言語処理系入門 4 7 関数の実装  抽象構文の拡張( syntax.ml ) let rec expr = … | AppExpr of expr * expr and value = … | FunVal of Symbol.t * expr  評価器の拡張 (eval.ml) let rec eval_expr env e = match e with … | AppExpr(e1,e2) -> clos_apply env (Value.get_clos (eval_expr env e1)) e2 and eval_value env v = match v with … | FunVal(x,e) -> Value.Clos(env,x,e) and clos_apply env (env',x,e') e = let xvs = eval_binds env [x,e] in eval_expr (Env.extend env' xvs) e'
  • 8. 2009/11/13 言語処理系入門 4 8 Syntax sugar  複数の引数を持つ関数 [[fn x1 x2 … xn -> E]]⇒ fn x1 -> (fn x2 -> … (fn xn -> [[E]])…)  let による関数定義 [[let f x1 … xn = E]]⇒   let f = [[fn x1 … xn -> [[E]] ]]  関数適用 [[E1 E2 … En]]⇒ (…(([[E1]] [[E2]]) [[E3]]) … [[En]]) カリー化という
  • 9. 2009/11/13 言語処理系入門 4 9 再帰的定義のための let rec 形式  再帰関数を定義するには,普通に let を使っ てもダメ let fact = fn n -> if n == 0 then 1 else n * fact(n – 1) in fact 5  let rec 形式を導入する  = の右辺式を拡張した環境の下で評価する },,{' | |'1for|' 11 11 nn nn ii vxvx vEExEx vEnivE   ±= ⇓==− ⇓−≤≤⇓− ρρ ρ ρρ inandreclet
  • 10. 2009/11/13 言語処理系入門 4 10 let rec の実装  eval.ml let rec eval_expr env e = match e with … | LetRecExpr(ds,e1) -> let env' = eval_rec_decls env ds in eval_expr env' e1 … and eval_rec_decls env ds = let env' = Env.extend env (List.map (fun (x,e) -> x,Value.UndefinedObj) ds) in let xvs = eval_binds env' ds in Env.updates env' xvs; env' 仮の値で環境 を拡張 後で正式な値 で環境を更新
  • 11. 2009/11/13 言語処理系入門 4 11 let rec を使わない再帰関数定義  以下のように fix オペレータ(関数)を定義する let fix f = (fn x -> f (fn y-> x x y)) (fn x -> f (fn y-> x x y))  例: factorial 関数の定義 # let factorial = fix (fn fct n -> if n == 0 then 1 else n * fct (n – 1)); # factorial 5; ==> 60  演習問題:  fix オペレータが動くことを確認し,なぜ再帰を生み出すのか 考えよ
  • 12. Syntax sugar(2)  begin ~ end 文の実装 [[begin E1; E2; … ; En end]]⇒ let _ = [[E1]] in let _ = [[E2]]in … in [[En]]  while 文の実装 [[while E1 do E2]]⇒ let rec loop x = if x then begin [[E2]]; loop [[E1]]end in loop [[E1]] 2009/11/13 言語処理系入門 4 12 loop, x はフレッシュな 変数 ( E1,E2 中に出現しな い)
  • 13. 参照呼び出し( Call-by- Reference )  swap 関数を定義したい # let x = 3 and y = 4; # swap x y;  x ==> 4, y ==> 3 となる  以下のように定義してもうまくいかない let swap x y = let temp = x in begin x := y; y := temp end;  引数 x と y は関数呼び出し時にコピーされてしまう 2009/11/13 言語処理系入門 4 13 )',(|, )',(|},,{},,,{ 1for),(|, 22110 111 1 SvEExExExS SvElxlxvlvlS niSvES nn nnnnin iiii ⇓===− ⇓−± ≤≤⇓−− inandandlet   ρ ρ ρ niSDOMl ni ≤≤∉ 1eachfor)(if
  • 14. 参照呼び出しのセマンティクス  右辺式が変数ならば,コピーしない  環境の実装  環境に格納する値が,直接的な値 ( DirectObject )か参照値( IndirectObject )か を区別できるようにする 2009/11/13 言語処理系入門 4 14 )',(|, )',(|}{, SvEyxS SvElxS ⇓=− ⇓−± inletρ ρ  )( ly =ρ Direct Int 5 Indirect x y
  • 15. 参照呼び出しの実装  参照はがし let deref = function | Value.DirectObj v -> v | Value.IndirectObj loc -> ( match Loc.get_val loc with | Value.DirectObj v -> v | Value.IndirectObj _ ->            raise Invalid_reference_error | Value.UndefinedObj x ->            raise (Undefined_variable_error x) )    | Value.UndefinedObj x ->       raise (Undefined_variable_error x)  評価器 let rec eval_expr env e = match e with … | VarExpr x -> deref (Env.lookup env x) 2009/11/13 言語処理系入門 4 15
  • 16. 参照呼び出しの実装(2)  参照先設定 let setref loc v = let loc' = match Loc.get_val loc with | Value.IndirectObj loc'' -> loc'' | _ -> loc in Loc.set_val loc' (Value.DirectObj v)  評価器 (eval_expr) | AsgnExpr(x,e1) -> let v = eval_expr env e1 in setref (get_var_loc env x) v; v 2009/11/13 言語処理系入門 4 16
  • 17. 参照呼び出しの実装(3)  変数束縛の処理 and eval_bind env (x,e) = x,(match e with | VarExpr x' -> let loc = get_var_loc env x' in ( match Loc.get_val loc with | Value.IndirectObj loc' -> Value.IndirectObj loc' | _ -> Value.IndirectObj loc ) | _ -> Value.DirectObj(eval_expr env e) ) 2009/11/13 言語処理系入門 4 17
  • 18. 名前呼び出し( Call by Name )  関数呼び出し時に,引数を評価しない.  関数の中で実際に引数を使うときに評価する  値呼び出しと名前呼び出しとでの重要な動作の 違い # let rec loop x = loop x; # let do_nothing x = 0; # do_nothing (loop 0); ???  値呼び出しだと無限ループするが,名前呼び出 しだと停止する  実用的な使い途として無限ストリームの実装に使える 2009/11/13 言語処理系入門 4 18
  • 19. 無限ストリームの例 // cons の手続き的な実装 let cons ?x ?y = fn m -> if m then x else y; let car b = b true; let cdr b = b false; // 無限ストリームの実装 let generator n = cons n (generator (n + 1)); # let stream = generator 0; # car stream; ==> 0 # car (cdr stream); ==> 1 # car (cdr (cdr stream)); ==> 2 … 以下メモリの続く限り 2009/11/13 言語処理系入門 4 19
  • 20. 名前呼び出しの実装  関数適用のとき,引数を評価せず,かわりにサ ンクオブジェクト(引数なしの関数)を作成し ,束縛する. (* サンクオブジェクトを作成する *) and thunk env e =    Value.ThunkObj    (fun () -> eval_expr env e)  変数を評価するときに,対象がサンクオブジェ クトの場合は,サンクオブジェクトを呼び出し て結果を得る.  サンプルプログラムでは deref 関数内で処理 let deref = function … | Value.ThunkObj t -> t()2009/11/13 言語処理系入門 4 20
  • 21. 演習課題  今週のサンプルプログラムを動かしてみよ  サンプルプログラムでは,値呼び出し,名前呼び出し参照呼び 出しを実装してある.  値呼び出しの場合  let x = E, let f x = E  参照呼び出しの場合  let &x = E, let f &x = E のように変数名の前に & をつける  名前呼び出しの場合  let ?x = E, let f ?x = E のように変数名の前に ? をつける  以下の挙動を確認せよ  let rec x = x;  let rec &x = x;  let rec ?x = x;  上の結果の違いをそれぞれ説明せよ 2009/11/13 言語処理系入門 4 21
  • 22. 2009/11/13 言語処理系入門 4 22 次回予定  日時:  2009 年 11 月 20 日(金) 17 : 00 - 18 : 30  場所:  LB2 3F/A 会議室  内容:  いろいろなデータ型の扱い  タグ付きレコード,文字列 etc.