081-set-bang.scm (1658B)
1 ; (set! name value) -- mutate an existing binding in place. Returns 2 ; unspecified. Must work on globals, lexicals (let-bound, lambda-bound), 3 ; and lexicals captured by a closure (mutation visible to all closures 4 ; that captured the same binding). 5 6 ;; --- Global rebind ---------------------------------------------------- 7 (define g 1) 8 (set! g 2) 9 (if (= g 2) 0 (sys-exit 1)) 10 11 ;; --- Lexical (let-bound) --------------------------------------------- 12 (if (= 9 13 (let ((x 1)) 14 (set! x 9) 15 x)) 16 0 (sys-exit 2)) 17 18 ;; --- Lexical, set! does NOT escape the let ------------------------- 19 ;; Outer g is unaffected by the inner set! on a shadowing binding. 20 (define outer-touched 0) 21 (let ((g 100)) 22 (set! g 200) 23 (set! outer-touched g)) 24 (if (= g 2) 0 (sys-exit 3)) ; outer g unchanged 25 (if (= outer-touched 200) 0 (sys-exit 4)) ; inner saw 200 26 27 ;; --- Lambda parameter -------------------------------------------------- 28 (define (bump x) (set! x (+ x 1)) x) 29 (if (= (bump 4) 5) 0 (sys-exit 5)) 30 31 ;; --- Closure-captured cell: counter pattern -------------------------- 32 (define counter 33 (let ((n 0)) 34 (lambda () 35 (set! n (+ n 1)) 36 n))) 37 38 (if (= (counter) 1) 0 (sys-exit 6)) 39 (if (= (counter) 2) 0 (sys-exit 7)) 40 (if (= (counter) 3) 0 (sys-exit 8)) 41 42 ;; --- Two closures sharing the same captured cell --------------------- 43 ;; Both closures close over the same `s`; mutations through one are 44 ;; visible through the other. 45 (define get #f) 46 (define put #f) 47 (let ((s 10)) 48 (set! get (lambda () s)) 49 (set! put (lambda (v) (set! s v)))) 50 51 (if (= (get) 10) 0 (sys-exit 9)) 52 (put 42) 53 (if (= (get) 42) 0 (sys-exit 10)) 54 55 (sys-exit 0)