作者noctem (noctem)
看板PLT
标题Re: [问题] letrec 为何可以成立? (In scheme, ma …
时间Wed Jun 2 20:58:37 2010
※ 引述《SansWord (是你)》之铭言:
: 课程上正在用scheme实作一个interpreter(mini-scheme),有environment机制
: 概念上是先订一组global environment
: 另外这个interpreter也支援high order function.
: 在这interpreter里面,lambda function evaluation的实作是:
: (eval (lambda ( arguments ) (function body) ) env )
Ok ok... 由於东西比较多,我用我比较熟悉的 "pseudo Haskell" 的
语法混合一些你的符号解释一下,希望看得懂....
假设我们定义一个小语言,有数字、加减法、lambda, LET, LETREC
等等(我把被解译的语言的关键字写成大写)。函数 eval 大约是像这样
eval n env = n -- 看到数字就传回数字
eval a env = lookup a env -- 看到变数就去环境里查查看
eval (\a.e) env = (%func a e, env)
--%func 应该是某个资料结构,表示这个 closure, 把目前的环境记下来
eval (e1 e2) env =
let (%func a body, env') = eval e1 env
v2 = eval e2 env
in eval body ((a,v2):env')
-- 把 env' (而不是 env) 扩充後去执行 body
Let 怎麽做呢?大约是这样
eval (LET a=e1 IN e2) env =
let v1 = eval e1 env
in eval e2 ((a,v1):env)
其实 LET 的 case 像是前面两个 case 的合体。确实有些函数语言
中会说
LET a = e1 IN e2
其实就是
(\a. e1) e2
另外我们会发现我们是用 host 语言的 let 在定义被解译的语言的 let.
那 LETREC 呢?如你所说,我们需要一个递回的环境。递回的环境怎麽产生呢?
既然 host 语言有 letrec, 那就用吧:
eval (LETREC a=e1 IN e2) env =
letrec env' = (a,v1) : env
v1 = eval e1 env'
in eval e2 env'
e1 要在 env' 这个环境中 eval, 而 env' 之中必须把
a 指到 e1 求值的结果 v1.
这麽做的条件是 host 语言已经有 letrec, 可以用来取递回定义的
解。如果没有,「没有 type」的 lambda calculus 也有办法取
取递回定义的 fixed-point (例如前面说的 Y combinator).
: 文章一开始提到的那个发问里面
: 有提到说如果语言机制里面允许 "mutable references" 就可以做到我正在做的事情
: 可是我想这也只是工具上的不同
这样则是比较「操作」的作法,直接用副作用去改环境。
如果是为了效率也许这样做比较好(不是很确定)。
避免用副作用则是让这个直译器有比较清楚的数学定义,
可以知道更多的性质。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 123.192.160.134