On this page:
4.9.1 Guidelines for Using Assignment
4.9.2 Multiple Values: set!-values
Version: 4.2.1

4.9 Assignment: set!

Assignment: set! and set!-values in Reference: PLT Scheme also documents set!.

Assign to a variable using set!:

(set! id expr)

A set! expression evaluates expr and changes id (which must be bound in the enclosing environment) to the resulting value. The result of the set! expression itself is #<void>.

Examples:

  (define greeted null)
  (define (greet name)
    (set! greeted (cons name greeted))
    (string-append "Hello, " name))
  > (greet "Athos")

  "Hello, Athos"

  > (greet "Porthos")

  "Hello, Porthos"

  > (greet "Aramis")

  "Hello, Aramis"

  > greeted

  ("Aramis" "Porthos" "Athos")

  (define (make-running-total)
    (let ([n 0])
      (lambda ()
        (set! n (+ n 1))
        n)))
  (define win (make-running-total))
  (define lose (make-running-total))

 

  > (win)

  1

  > (win)

  2

  > (lose)

  1

  > (win)

  3

4.9.1 Guidelines for Using Assignment

Although using set! is sometimes appropriate, Scheme style generally discourages the use of set!. The following guidelines may help explain when using set! is appropriate.

All else being equal, a program that uses no assignments or mutation is always preferable to one that uses assignments or mutation. While side effects are to be avoided, however, they should be used if the resulting code is significantly more readable or if it implements a significantly better algorithm.

The use of mutable values, such as vectors and hash tables, raises fewer suspicions about the style of a program than using set! directly. Nevertheless, simply replacing set!s in a program with a vector-set!s obviously does not improve the style of the program.

4.9.2 Multiple Values: set!-values

Assignment: set! and set!-values in Reference: PLT Scheme also documents set!-values.

The set!-values form assigns to multiple variables at once, given an expression that produces an appropriate number of values:

(set!-values (id ...) expr)

This form is equivalent to using let-values to receive multiple results from expr, and then assigning the results individually to the ids using set!.

Examples:

  (define game
    (let ([w 0]
          [l 0])
      (lambda (win?)
        (if win?
            (set! w (+ w 1))
            (set! l (+ l 1)))
        (begin0
          (values w l)
          ; swap sides...
          (set!-values (w l) (values l w))))))
  > (game #t)

  1

  0

  > (game #t)

  1

  1

  > (game #f)

  1

  2