操作Scheme评估程序

时间:2013-04-19 17:58:06

标签: scheme racket

我正在尝试操作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 。但我不确定应该改变什么....

1 个答案:

答案 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,然后重试。