求值环境模拟
环境 构建和操作
SICP 的环境构建思路
frame 相关操作
SICP 是将环境实现为框架的表,每个框架包含一个variable的链表和一个value的链表
比如:
variable 'a 'b 'c 'd value: 1 2 3 4
frame提供操作 :(make-frame variables values) ;;cons variables values
(frame-variables frame) ;;car frame
(frame-values frame) ;;cdr frame
(add-binding-to-frame var val frame)
解释一下: 分别是
根据一个variables和values的链表构造一个frame
取出variables链表
取出values 链表
添加新的var-value在frame中
env 定义
empty-env
(outer-env env) ;;cdr env
(first-frame env) ;;cdr env(lookup var env)
(set-var! var new-value env)
(def-var! var new-value env)
解释一下:
- env 的定义就是frame的链表
- empty-env就是空环境,直接定义为nil( '() )
- outer-env 就是除了当前框架外的外部环境
+first-frame就是当前环境
后面的三个操作十分重要,首先是从环境中找到variable对应的value
- 第二个是改变环境中var的值
- 在当前环境中定义变量var
个人的构造方式
source code
#lang planet neil/sicp
(define (make-env variable value)
(if (=(length variable)(length value) )
(map cons variable value)
(error "the numbers of variable and value doesn't match!") ))
(define (env-variable env)
(map car env))
(define (env-value env)
(map cdr env))
(define (add-binding-to-env! var val env)
(cons (cons var val) env))
(define (lookup-var var env)
(cond ((null? env) '())
((eq? var (car (env-variable env))) (car (env-value env)))
(else (lookup-var var (cdr env))
)))
(define (set-var! var new-value env)
(cond ((null? env) '())
( (eq? var (car (env-variable env)))
(set-car! env (cons var new-value)))
(else (set-var! var new-value (cdr env)))))
(define (def-var! var new-value env)
(cond ((null? env) (add-binding-to-env! var new-value env))
((eq? var (car (env-variable env))) (set-car! env (cons var new-value)) )
(else (set-car! env (cons (cons var new-value) (car env) ) ))))
介绍
大致的思路是,将env表示成 pair 变量的链表,每个pair是var-val键对
- make-env:
首先检查variables和values元素个数是否相等,若相等则利用map进行cons:
举例: variables: ('a 'b 'c' d)
values: (1 2 3 4)
map之后: (('a 1) ('b 2) ('c 3) ('d 4)) - empty-env 空环境仍然定义为nil
- 提取variables和values的操作仍然由map来完成
- 接下来由4个操作:添加新的var-val在env的开头、lookup、set-var!、def-var!
- 另外,在racekt中set-car! 没有定义,因此这里第一行说明语言为mit-scheme;
- set-car! 等赋值操作只对已经定义的变量有效,而对(set-car! (some-op data) new-value)无效
分析
- 其实环境的实现方式不重要,引用第二章的界面约定和抽象屏障的思想,我们只要提供满足约定的界面或者说是接口即可;
- S型表达式使得我们解析语法结构变得很容易,当然配合scheme本身也是这样的语法结构就更简单了,但是用其它语言来做也大同小异,需要补写一个词法分析
- 我们的ICS 课程的实验任务是在给定的框架下实现一个完整的模拟器:需要对IA32的绝大多数指令给出模拟,并且需要实现常见的如断点、打印栈帧链、单步执行等功能,也包括程序的加载等等。当然这是用C语言做的啦。 做起来还是很爽的,收获也很大。不过扫了一下第五章用scheme做一个简单的寄存器模拟(貌似只有3条简单的指令),用scheme来写的话,模拟器的速度就更加不忍直视了。。哈哈
- 但是我个人感觉scheme 的好处就在于抽象层次很高,完全不用担心任何硬件细节,实际程序的效率可能不高,但是用scheme实现同样功能之后收获往往会更大,对这一问题的理解往往到达更加抽象的层次。
- 最后,其实相对于纯C,个人更喜欢C++,毕竟提供给了更多的可能,对个人写程序而言,更容易符合自己的胃口,C的话不免用很多宏来抽象,不太符合个人对语言的审美。
- 实验使用的环境是Drracket