CSE 341 -- Scheme Wrapup

Assignment and List Surgery

Scheme does provide assignment operators. They generally end with a bang (!). They include set!, set-car!, set-cdr!. Examples:
(define foo 'bar)
(define numbers '(1 2 3 4))

(set! foo 'boo)
(set-car! numbers 1000)
numbers   => (1000 2 3 4)
             
(set-cdr! numbers '(7 8 9))
numbers   => (1000 7 8 9)

;; making a circular list:
(define circ '(1))
(set-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 'newt))

(define animals '(rabbit horse squirrel monkey))
(change-it animals)


I/O

Scheme provides simple I/O primitives:
(display <some-object>)       ; general form for printing
(newline)                           ; force a newline

;; example a simple way to trace a function

(define length
  (lambda (x)
    (display (list 'in-length x))
    (newline)
    (cond 
     ((null? x) 0)
     (#t (+ 1 (length (cdr x)))))))

(length '(boo bar))           => ; the output follows...
(in-length (boo bar))
(in-length (bar))
(in-length ())
2
Of course, the language also provides primitives for opening and reading/writing files.

Exceptions

The Scheme language doesn't define a particularly easy-to-use error handling mechanism (or rather, it provides the tools for building such a mechanism, which are beyond the scope of this class). Many dialects, however, provide some support. In DrScheme, for instance defines an error hierarchy, which looks something like this:
;  exn                    ; supertype
;    user                 ; errors raised by user
;    application          ; system errors
;      divide-by-zero
;      type
;      arity
;    i/o                  ; i/o errors
;    etc

;; It provides predicates for testing for objects for their type:
exn?
exn:user?
exn:application?
exn:applicaton:divide-by-zero?
We can then raise and catch errors as follows:
(error <symbol>)      ; the general form for raising an error

(with-handlers <handlers> <body>)    ; the catch expression

(with-handlers
 ((exn:user?                        (lambda (exn) 'caught-user-error))
  (exn:application:divide-by-zero?  (lambda (exn) 'caught-div-zero-error))
  (exn:application:type?            (lambda (exn) 'caught-type-error)))
 (/ 1 0))         => 'caught-div-zero-error

(with-handlers
 ((exn:user?                        (lambda (exn) 'caught-user-error))
  (exn:application:divide-by-zero?  (lambda (exn) 'caught-div-zero-error))
  (exn:application:type?            (lambda (exn) 'caught-type-error)))
 (+ 1 "hello"))         => 'caught-type-error

(with-handlers
 ((exn:user?                        (lambda (exn) 'caught-user-error))
  (exn:application:divide-by-zero?  (lambda (exn) 'caught-div-zero-error))
  (exn:application:type?            (lambda (exn) 'caught-type-error)))
 (error 'foobar))      => caught-user-error


dugan@cs.washington.edu (Last Update: )