CSE 341 - Programming Languages - Winter 2010

Side Effects in Scheme

When To Use Side Effects in Scheme?

Assignment and List Surgery

Scheme includes a special form for assignment:
 (set! var expr) 
(define x 10)
(write x)
(set! x (+ x 1))
(write x)

You can only use set! on a variable after it's been defined.

There are also functions set-car! and set-cdr! to assign into the car or cdr of a cons cell. Finally, there is a special form do for iteration.

Caution!! In recent versions of Dr Scheme (e.g. 4.1.2 and 4.1.3, which are the versions on the CSE ugrad linux and windows machines), set-car! and set-cdr! are available in R5RS but not in the Pretty Big dialect. In Pretty Big, they are called set-mcar! and set-mcdr!, and only work on mutable cons cells (created with mcons), and more generally on mutable lists; but not on ordinary cons cells and lists.

Example (in R5RS) -- change to make a mutable list for latest Pretty Big:

(define x '(1 2 3 4))
(write x)     ; prints (1 2 3 4)
(set-car! x 100)
(write x)     ; prints (100 2 3 4)
(set-cdr! x ())
(write x)     ; prints  (100)
Making a circular list:
(define circ '(a b))
(set-cdr! (cdr circ) circ)
When you pass a list to a function in Scheme, a reference to the list is passed, rather than a copy. Thus, if you use set-car! or set-cdr! to do list surgery inside the function, the actual parameter will be affected.
(define (change-it x)
    (set-car! x 'frog))

(define animals '(rabbit horse squirrel monkey))
(change-it animals)
However, consider:
(define (test x)
   (write x)
   (set! x 100)
   (write x))

(define y '(1 2 3))
(test y)  ; prints (1 2 3) then 100
(write y) ; prints (1 2 3) ... y is unaltered

Pretty Big lets you define 'structs'. (This isn't in R5RS however.) For example:
(define-struct point (x y))

;; we now have accessors, tests, and setters defined:
(define p (make-point 10 10))

;; try these:
;; (point? p)
;; (point-x p)
;; (point-y p)
;; (point-y p)
;; (set-point-x! p 100)
;; (set-point-y! p 200)

(define (dist p1 p2)
  (let ((dx (- (point-x p1) (point-x p2)))
        (dy (- (point-y p1) (point-y p2))))
    (sqrt (+ (* dx dx) (* dy dy)))))

(define a (make-point 0 0))
(define b (make-point 3 4))

;; (dist p1 p2)

A struct is not any existing type in Scheme -- it's a new beast!
(define (what-is-it v)
  (cond ((number? v) 1)
        ((procedure? v) 2)
        ((cons? v) 3)
        ((string? v) 4)
        ((symbol? v) 5)
        ((null? v) 6)
        (else 7)))