(set! var exp) | syntax |
returns: unspecified |
set! does not establish a new binding for var but rather alters the value of an existing binding. It first evaluates exp, then assigns var to the value of exp. Any subsequent reference to var within the scope of the altered binding evaluates to the new value.
It is an error to assign a top-level variable that has not yet been defined, although many implementations do not enforce this restriction.
Assignments are not employed as frequently in Scheme as in most traditional languages, but they are useful for implementing state changes.
(define flip-flop (let ((state #f)) (lambda () (set! state (not state)) state))) (flip-flop) ⇒ #t (flip-flop) ⇒ #f (flip-flop) ⇒ #t
Assignments are also using for caching values. The example below uses a technique called memoization, in which a procedure records the values associated with old input values so it need not recompute them, to implement a fast version of the otherwise exponential doubly-recursive definition of the Fibonacci function (see page 66).
(define memoize (lambda (proc) (let ((cache '())) (lambda (x) (cond ((assq x cache) => cdr) (else (let ((ans (proc x))) (set! cache (cons (cons x ans) cache)) ans))))))) (define fibonacci (memoize (lambda (n) (if (< n 2) 1 (+ (fibonacci (- n 1)) (fibonacci (- n 2))))))) (fibonacci 100) ⇒ 573147844013817084101