;; Imperative Programming: Modifying State. ;; ;; Exercise 2.26 ;; ;; Since vectors are mutable, we use a one-element vector to ;; store the reference value. (define-datatype reference reference? (a-ref (position integer?) (vec vector?))) ;; Cell interface operatios: cell, cell?, contents, setcell (define cell (lambda (value) (a-ref 0 (vector value)))) (define cell? reference?) (define contents (lambda (c) (cases reference c (a-ref (pos vec) (vector-ref vec pos))))) (define setcell (lambda (c newvalue) (cases reference c (a-ref (pos vec) (vector-set! vec pos newvalue))))) ;; e.g.: (let ((c1 (cell 5)) (c2 (cell 10))) (begin (setcell c2 (+ (contents c1) (contents c2))) (setcell c1 (contents c2)) (contents c1))) (cell? (cell 0)) ;; ;; An object-based version of the cell data type. ;; (define cell (lambda (value) (let ((ref (a-ref 0 (vector value)))) (letrec ((cell? (lambda () #t)) (contents (lambda () (cases reference ref (a-ref (pos vec) (vector-ref vec pos))))) (setcell (lambda (newval) (cases reference ref (a-ref (pos vec) (vector-set! vec pos newval)))))) (vector cell? contents setcell))))) (define cell-get-cell?-operation (lambda (c) (vector-ref c 0))) (define cell-get-contents-operation (lambda (c) (vector-ref c 1))) (define cell-get-setcell-operation (lambda (c) (vector-ref c 2))) ;; e.g.: (let ((c1 (cell 5)) (c2 (cell 10))) (let ((get1 (cell-get-contents-operation c1)) (get2 (cell-get-contents-operation c2)) (set1 (cell-get-setcell-operation c1)) (set2 (cell-get-setcell-operation c2))) (begin (set2 (+ (get1) (get2))) (set1 (get2)) (get1)))) ((cell-get-cell?-operation (cell 0))) ;; Exercise: add a get-set-cell operation that gets the current value ;; of the cell and then replaces it for a given new value. ;; ;; Examples of section 3.7 ;; (load "3-7.scm") (run " let x = 0 in letrec even() = if zero?(x) then 1 else let d = set x = sub1(x) in (odd) odd() = if zero?(x) then 0 else let d = set x = sub1(x) in (even) in let d = set x = 13 in (odd) ") (run " let g = let count = 0 in proc() let d = set count = add1(count) in count in +((g), (g)) ") (run " let x = 100 in let inc = proc (x) let d = set x = add1(x) in x in +((inc x), (inc x)) ") ;; as opposed to: (run " let x = 100 in let inc = proc () let d = set x = add1(x) in x in +((inc), (inc)) ") ;; Do exercise 3.39, so we do not need to use a ;; dummy variable "d" for sequencing and we could ;; write instead: (run " let x = 0 in letrec even() = if zero?(x) then 1 else begin set x = sub1(x); (odd) end odd() = if zero?(x) then 0 else begin set x = sub1(x); (even) end in begin set x = 13; (odd) end ") ;; Try out exercises 3.41, and 3.43.