|
|
<式> | ::= | … |
| | fun <識別子> → <式> | |
| | <式1> <式2> |
syntax.ml:
type exp = ... | FunExp of id * exp | AppExp of exp * exp
parser.mly:
%token RARROW FUN Expr : ... | FunExpr { $1 } MExpr : MExpr MULT AppExpr { BinOp (Mult, $1, $3) } | AppExpr { $1 } AppExpr : AppExpr AExpr { AppExp ($1, $2) } | AExpr { $1 }
lexer.mll:
let reservedWords = [ ... ("fun", Parser.FUN); ... ] ... | "=" { Parser.EQ } | "->" { Parser.RARROW }
Figure 8: 関数と適用(1)
|
Expressed Value | = | 整数 (…, -2, -1, 0, 1, 2, 3, …) + 真偽値 + 関数値 |
Denoted Value | = | Expressed Value |
let x = 2 in let addx = fun y → x + y in addx 4x の静的束縛を実現するためには,この addx の適用を行う際には 本体中の x が 2 であることを記録しておかなければならない. というわけで,一般的に関数が適用される時には,
eval.ml:
type exval = IntV of int | BoolV of bool | ProcV of id * exp * dnval Environment.t and dnval = exval let rec eval_exp env = function ... | FunExp (id, exp) -> ProcV (id, exp, env) | AppExp (exp1, exp2) -> let funval = eval_exp env exp1 in let arg = eval_exp env exp2 in (match funval with ProcV (id, body, env') -> let newenv = Environment.extend id arg env' in eval_exp newenv body | _ -> err ("Non-function value is applied"))
Figure 9: 関数と適用(3)
let threetimes = fun f → fun x → f (f x x) (f x x) in threetimes (+) 5は,20を出力する.
fun x1 ... xn → ... let f x1 ... xn = ...といった簡略記法をサポートせよ.
let makemult = fun maker → fun x → if x < 1 then 0 else 4 + maker maker (x + -1) in let times4 = fun x → makemult makemult x in times4 3
let a = 3 in let p = fun x → x + a in let a = 5 in a * p 2というプログラムで,関数p本体中の a は 3 ではなく 5 に束縛される.インタプリタを改造し,動的束縛を 実現せよ.
let fact = fun n → n + 1 in let fact = fun n → if n < 1 then 1 else n * fact (n + -1) in fact 5