我正在尝试操作Scheme评估器并编写一个make-unbound!
过程来解除环境中的变量:
(define (make-unbound! var env)
(let ((frame (first-frame env)))
(define (scan vars vals)
(let ((new-frame
(make-frame
(zip
(filter (lambda (x) (not (eq? x (car vars)))) vars)
(filter (lambda (x) (not (eq? x (car vals)))) vals))
env)))
(cond ((null? vars)
(display '(No frame to unbind)))
((eq? var (car vars))
(set-car! vars new-frame)) ; the problem seems to be here
(else (scan (cdr vars) (cdr vals))))))
(scan (frame-variables frame)
(frame-values frame))))
问题似乎在于我在哪里设置变量的 car 。但我不确定应该改变什么....
答案 0 :(得分:1)
这看起来像SICP的练习4.13。可以使用Racket评估make-unbound!
特殊表单:
(define (remove-association! key lst)
(define (loop prev l)
(cond ((null? l) lst)
((equal? (mcar (mcar l)) key)
(set-mcdr! prev (mcdr l))
lst)
(else (loop l (mcdr l)))))
(cond ((null? lst) '())
((eq? (mcar (mcar lst)) key) (mcdr lst))
(else (loop lst (mcdr lst)))))
(define (unbind-variable! var env)
(define (env-loop env)
(define (scan bindings)
(cond ((massq var bindings)
(set-mcar! env (remove-association! var bindings)))
(else (env-loop (enclosing-environment env)))))
(unless (eq? env the-empty-environment)
(scan (first-frame env))))
(env-loop env))
(define (unbound-variable exp)
(cadr exp))
(define (eval-make-unbound! exp env)
(unbind-variable! (unbound-variable exp)
env))
它删除了使用给定符号找到的第一个绑定,无论是在当前帧还是其任何封闭环境中。如果符号首先未绑定,则不执行任何操作。我选择以这种方式实现unbind操作,以便封闭环境中的(可能的)绑定保持不变。
不要忘记在eval
程序中指定使用make-unbound!
程序评估特殊表单eval-make-unbound
。
另外,请注意我使用Racket的可变对库进行了实现,因此我使用的过程名称有时在其名称中有一个额外的m
,意思是:它们是为定义的可变的对。例如:mcar, mcdr, set-mcar!, set-mcdr!, massq
。如果找不到任何先前的过程,只需从名称中删除m
,然后重试。