In this lecture we explore one of the most powerful features of Scheme -- the notion of a list.
(define familynames '(Tim Yas Shaye Caitlin Ryan)) (define familystrings '("Tim" "Yas" "Shaye" "Caitlin" "Ryan")) (define product '(* 1 2 3 4 5)) (define arithexprs '((* 1 2) (* 3 4) (* 5 6))) (define emptylist '()) (define listoflists '((Tim 3) (Yas 3) (Shaye 5) (Caitlin 7) (Ryan 4))) (define responses '((That is very interesting. Please go on.) (Could you tell me about your relationship with your father?) (Do you really believe that?) (You seem a little uncomfortable. Are you?) (Are you getting angry?) (I am here to listen. Just relax and start talking.) ) ) (define formula '(+ 5 (* 3 (sin x)))) (define oneToTen '(1 2 3 4 5 6 7 8 9 10))The single quote is a piece of Scheme syntax that directs the interpreter to leave the following Scheme term as is. Thus, in each of the cases the quoted lists are assigned as is to the specifed variables. In particular
(* 1 2 3 4 5)
is NOT evaluated to get 120, it is simply left as a list containing 6 elements.
Another way to create lists is with the "list" function. This creates a list of
its arguments
(define listA (list 1 2 3 4))
(define listB (list (* 1 2) (* 3 4) (* 5 6)))
(define listC (list (list 'a 'b 'c) (list 'd 'e 'f)))
(define listD (list (textfield "a" 10) (textfield "b" 10) (textfield "c" 10) (textfield "d" 10)))
The "list" function evaluates its arguments so in particular listB would
be bound to '(2 12 30), not '((* 1 2) (* 3 4) (* 5 6)). Similarly, listD will get bound
to a list containing four textfields.
(null? L)
is true if the list L is empty
(first L)
returns the first element of the list L
(rest L)
returns the list L, but with the first element removed
(cons X L)
creates a new list by adding X to the beginnning of list L
(length L)
returns the length of the list L
(null? ()) ;==> #t (null? '(a b c)) ;==> #f (first '(a b c)) ;==> a (rest '(a b c)) ;==> (b c) (rest '(a)) ;==> () (cons 'a '(b c)) ;==> (a b c) (cons 'a '()) ;==> (a)
(append LIST1 LIST2)
. This combines the two lists:
(append '(1 2 3) '(a b c)) ;==> '(1 2 3 a b c)
(apply FUNCTION LIST)
. This takes the function and calls
it with the LIST as its argument. For example,
(define oneToTen '(1 2 3 4 5 6 7 8 9 10)) (apply + oneToTen) ;==> 55 (apply * '(1 2 3 4)) ;==> 24 (apply window (list 100 100 "Hello World" (button "hi"))) ;==> a window with a "hi" buttonThus,
(apply F (list A B C ... Z))
is equivalent to
(F A B C ... Z)
.
(map FUNCTION LIST)
this applies the function to each element
of the list.
(define (sq x) (* x x)) (map sq oneToTen) ;==> '(1 4 9 16 25 36 49 64 81 100) (define squares (map sq oneToTen)) (apply + (map sq '(1 2 3))) ;==> 14In the next example we show how to create a list of windows which can be opened and closed as a group.
(define (makewin T) (window T (label T (CourierBold 36)) red)) (define (sleep N) (Thread.sleep (.longValue N))) (define windows (map makewin '("Konichi-wa" "Gutten Tag" "Bon Jour" "Shalom" "Hola" "Hi"))) (map .pack windows) (map .show windows) (sleep 10000) (map .hide windows) (sleep 1000) (map .show windows) (sleep 2000) (map .hide windows) (sleep 1000) (map .show windows)Next we show how to add up the numbers in a list of textfields:
(define days '("mon" "tue" "wed" "thu" "fri" "sat" "sun")) (define vals '("1" "2" "3" "4" "5" "6" "7")) (define (mytextfield X) (textfield X 10)) (define daylabels (map label days)) (define dayfields (map mytextfield vals)) (define (sumdays) (apply + (map readexpr dayfields))) (define total (textfield "" 10 white)) (define win (window "demo" yellow (border (center (apply grid (append '(2 7) daylabels dayfields))) (south total) (north (button "sum" pink (action (lambda (e) (writeexpr total (sumdays))))))))) (.pack win) (.show win)
(list-ref L n)
which
selects the n-1st element of a list L.
(list-ref '(a b c d) 0) ; --> a (list-ref '(a b c d) 3) ; --> dThe code for the scheme procedure
(rand n)
uses the Java literals Math.random, Math.round,
and .intValue
to generate
a random whole number between 0 and n-1.
(define (rand N) (.intValue (Math.round (* (- N 1) (Math.random))))) (rand 100) ;--> 57 (rand 100) ;--> 32 (rand 100) ;--> 89We now use these procedures to define
select-rand
as shown below:
;; select a random element of the list L (define (select-rand L) (list-ref L (rand (length L)))) (select-rand '(a b c d e f g)) ; --> d (select-rand '(a b c d e f g)) ; --> b (select-rand '(a b c d e f g)) ; --> g
(define (rand N)
(.intValue (Math.round (* (- N 1) (Math.random)))))
(define (select-rand L)
(list-ref L (rand (length L))))
(define responses
'((Hmmm. That's interesting.)
(Really)
(Could you tell me about your relationship with your father?)
(Do you really believe that?)
(You seem a little uncomfortable. Are you?)
(Are you getting angry?)
(I am here to listen. Just relax and start talking.)
(OK. What is really bothering you.)
)
)
(define respond (action (lambda (e)
(writeexpr user "")
(writeexpr me (select-rand responses)))))
(define me (textfield "Hi" 80))
(define user (textfield "" 80 respond))
(define win (window "converse"
(col
(row (label "Dr. Silicon") me)
(row (label "Patient X ") user))))
(.pack win)
(.show win)
here is a link to the source code.