0
(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))))

The lookup procedure works well, but the set procedure can't change the val of the var.So here we are.

Scheme is call-by-value, so i doubt that the return value of merge doesn't share object with env. But i don't understand why it don't share.

append shares,map shares,cons shares,(i mean (define y (cons x x)) then you (set-car! x ...) the y will also change) but why doesn't a defined function share?

So i just want to get all of the vars and vals of env (i mean strip off the frame),then search or set them. But i stuck here.

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

This works,so it means the z is replaced by a pointer to x or the return value of merge is a copy of the "old",identical but independent?

When the formal parameter of merge(or others) is replaced by a list,is it a pointer to the list?

How does call-by-value works here?

How can I achieve my idea?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
S.Tian
  • 29
  • 2

1 Answers1

0

You use env-values and env-variables which effectively appends the frames together into one list. It does this by copying each element to a new list. Your set-car! alters a cons in that new list and does not change the original env.

You should make lookup iterate the original frames and variables and perhaps return the pair which holds the value. If not found you throw an error like (error "Unbound variable" var).

That way lookup-variable-value would become

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

And set-variable-value! would become:

(define (set-variable-value! var val env)
  (set-car! (lookup var env) val))
Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • Sorry,it doesn't work,the lookup in your solutions is different from mine,but i change mine based on your opinion, still doesn't work. And the append in the merge didn't creat – S.Tian Jun 28 '16 at 14:38
  • @S.Tian To be sure you implemented `lookup` correct this expression should be `#t`: `(let ((env '(((x) . (v))))) (eq? (lookup 'x env) (cdar env)))` – Sylwester Jun 28 '16 at 15:49
  • Sorry for my ugly comment, I have worked it out, Anyway, Thank you so much! – S.Tian Jun 28 '16 at 16:34