# Symbolic Processing in Scheme: Basic list processing

### References

In this lecture we explore one of the most powerful features of Scheme -- the notion of a list.

## Lists

A list is a sequence of Scheme terms enclosed in parentheses. Lists can be constructed in several ways. The simplest way is simply to put a single quote in front of the 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.)
(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.

## Basic operations on lists

• ` (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)
```

## More Operations on lists

Scheme offers several primitives for operating on lists.
• `(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" button
```
Thus, `(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)))
;==> 14
```
In 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)
(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)
```

## Selecting random elements from a list

One useful function which is included in the standard Scheme primitives is the `(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) ; --> d
```
The 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) ;--> 89
```
We 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

```

## A conversation program

```  (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)
(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)

```

## Dr. Silicon

Next we look at an applet which simulates a counselor. The key idea behind this applet is that it looks for keywords in the user's sentences and uses the keywords to select a list of "canned" responses. Selecting one of those responses at random provides the applet with the ability to respond somewhat "appropriately" to the user.

You need Java to view applets.

here is a link to the source code.