SICP ex4.12关于共享和按值调用

时间:2016-06-28 11:27:38

标签: scheme sicp

(define (make-frame var val)
  (cons var val))
(define (frame-variables frame) (car frame))
(define (frame-values frame) (cdr frame))
(define (add-binding-to-frame! var val frame)
  (set-car! frame (cons var (car frame)))
  (set-cdr! frame (cons val (cdr frame))))
(define (empty-env? env)
  (null? env))
(define (env-variables env)
 (define (merge x)
      (if (null? x)
    '()
    (append (car x) (merge (cdr x)))))
 (merge (map frame-variables env)))
(define (env-values env)
    (define (merge x)
      (if (null? x)
        '()
        (append (car x) (merge (cdr x)))))
    (merge (map frame-values env)))
(define (enclosing-environment env) (cdr env))
(define (first-frame env) (car env))
(define the-empty-environment '())
(define (lookup-variable-value var env)
(define (lookup variables values)
    (if (null? variables)
      (error "Unbound variable" var)
      (if (eq? var (car variables))
        (car values)
        (lookup (cdr variables) (cdr values)))))
  (lookup (env-variables env) (env-values env)))
(define (set-variable-value! var val env)
  (define (lookup-set! variables vals)
    (if (null? variables)
      (error "Sorry Unbound variable -- SET!" var)
      (if (eq? var (car variables))
        (set-car! vals val)
        (lookup-set! (cdr variables) (cdr vals)))))
  (lookup-set! (env-variables env) (env-values env))
  'ok)
(define test-env 
    (list (cons (list 'x 'y 'z) (list 1 2 3)) 
          (cons (list 'a 'b 'c) (list 4 5 6)) 
          (cons (list 'm 'n 'q) (list 7 8 9))))

lookup程序效果很好,但set程序无法改变var.So的val值。

Scheme是按值调用,因此我怀疑merge的返回值与env不共享对象。但我不明白它为什么不分享。

append股,map股,cons股,(我的意思是(define y (cons x x)),然后(set-car! x ...) y也会发生变化,但是为什么没有定义功能共享?

所以我只想获得env的所有变量和值(我的意思是剥离帧),然后搜索或设置它们。但我卡在这里。

(define x '(a b c))
(define (y z) (set-car! z 'change))
(y x) => (change b c)

这是有效的,这意味着z被指向x的指针取代,或merge的返回值是" old"的副本,相同但独立?

merge(或其他)的形式参数被列表替换时,它是否是指向列表的指针?

按值调用如何在这里工作?

我如何实现自己的想法?

1 个答案:

答案 0 :(得分:0)

您可以使用env-valuesenv-variables将这些帧有效地附加到一个列表中。 通过将每个元素复制到新列表来实现此目的。您的set-car!会更改新列表中的缺点,但不会更改原始env

您应该使查找迭代原始帧和变量,并且可能返回保存该值的对。如果没有找到,则抛出类似(error "Unbound variable" var)的错误。

那样lookup-variable-value会变成

(define (lookup-variable-value var env)
  (car (lookup var env)))

set-variable-value!将成为:

(define (set-variable-value! var val env)
  (set-car! (lookup var env) val))