University of California, Berkeley
EECS Department - Computer Science Division
CS3L OaW Lecture 10 : CAL (Cons Append List)
Announcements
- Midterm on Wed 2008-10-29 @ 6-9pm in 2050 VLSB:
- Conflicts/DSP email David (cs3-td@inst.eecs.berkeley.edu)
- Open book, open notes, covering everything up to and including HOFs and Lambda
(but not the TicTacToe example -- chapter 10, which you weren't supposed to read)
- Other admin questions?
Lists, aka "CAL : Cons, Append & List"
Overview
- We're going to motivate the need for lists by talking about the limitations of sentences.
- Sentences can't have nested sentences or booleans & procedures in it. E.g.,
: (define an-illegal-sentence
'(cs3 is great (but that is my (dans) opinion) and fun))
: (define another-illegal-sentence
'(#f #t #t))
- Lists can be thought of by thinking of sentences but relaxing both those constraints...
- Lists can be created by hand, and can contain any number of atoms
: '(yo whassup GoBears CS3isNumber 1)
==> (yo whassup gobears cs3isnumber 1)
- Just as expressions can be simple or complex...
: (+ 3 5)
==> 8
: (+ 1 (/ 4 2) (+ (- 5 1) (remainder (truncate 4.9) 3)))
==> 8
- ...lists can be simple or complex too! (in fact, if you look closely, you'll see the expression above was really a list in itself, ooooh!). In contrast, sentences can only be simple (i.e., not nested).
: (define simple '(1 2 3 4) )
==> simple
: simple ;; list OR sentence
==> (1 2 3 4)
: (define complex '(a (b c) () ((d)) ) )
==> complex
: complex ;; only lists can be complex
==> (a (b c) ((d)))
- Simple is a list of four elements, the atoms 1, 2, 3 and 4
- Complex is a list of three elements, the first the atom a, the second a list (containing two elements, atoms b and c), and the third is a list (nested, containing one element, which itself is a list containing d)
Data Structures
- Lists are often used as data structures, to store information
: (define meals
'((breakfast (3 rasberry poptarts)
(7 eggs)
(5 mango smoothies))
(lunch (2 advil)
(3 burritos)
(4 yoo-hoos))
(dinner (3 pepto-bismol)
(4 advil)
(2 nyquil)
(1 pearl milk tea))))
: meals
==> ((breakfast (3 rasberry poptarts)
(7 eggs)
(5 mango smoothies))
(lunch (2 advil)
(3 burritos)
(4 yoo-hoos))
(dinner (3 pepto-bismol)
(4 advil)
(2 nyquil)
(1 pearl milk tea)))
Selectors and Constructors Overview
- Whenever we discuss a new data type, we need to discuss the selectors and constructors.
- The primary selectors and constructors are (you can also find these in the back cover of the book):
- cons, list, append, car, cdr, length, null?, list?, list-ref
- We can use the variable L when using lists (uppercase L is better than lowercase l which looks like the number one ... 1), just as we used s for sentences.
Constructors
- Lists can contain no elements, this is called the null list (same printed representation as the empty sentence)
: '()
==> ()
- They can be created explicitly as we have seen so far
: '(this is a list)
==> (this is a list)
- ...or they can be created through constructors:
- (cons element list)
- Returnslist with element inserted at the start
- (Note that in general, the second argument to cons can be anything, but NOT IN CS3 ... in this class, the second argument to cons MUST BE a list)
- (append list1 list2 ... listn)
- Returns the list formed by concatenating the elements of list1 ... listn
- (list el1 el2 ... eln)
- returns the list (el1 el2 ... eln)
- Examples:
: (cons 'cs3 '())
==> (cs3)
: (cons 'love (cons 'cs3 '()))
==> (love cs3)
: (cons 'i (cons 'love (cons 'cs3 '())))
==> (i love cs3)
: (cons '(1 2) '(3 4))
==> ((1 2) 3 4)
: (list 1 2 5 'three-sir 3)
==> (1 2 5 three-sir 3)
: (list 1 2 5 '(3 sir) 3)
==> (1 2 5 (3 sir) 3)
: (append '(1 2) '(3 4))
==> (1 2 3 4)
: (append '(1) '(2 (3)) '() '(4 5 6) '(((7))) )
==> (1 2 (3) 4 5 6 ((7)))
- Ways you can think about it:
- cons stuffs its first argument into the paren of the second
- list just dissolves the word list
- append dissolves parenthesis around each element and itself
- And, taken together, these are the CAL functions (Cons Append List)!
Selectors
- The primary selectors are car and cdr:
- (car list)
- same as first, but for lists - i.e., return the first element of the list, if there is one.
- (cdr list)
- same as butfirst (pronounced "could-er"), but for lists - i.e., return all but the first element of the list.
: (define my-list
'(cs3 is great (but that is my (dans) opinion) and fun))
: my-list
==> (cs3 is great (but that is my (dans) opinion) and fun)
: (car my-list)
==> cs3
: (cdr my-list)
==> (is great (but that is my (dans) opinion) and fun)
: (cdr (cdr my-list))
==> (great (but that is my (dans) opinion) and fun)
: (cdr (cdr (cdr my-list)))
==> ((but that is my (dans) opinion) and fun)
: (cdr (cdr (cdr (cdr my-list))))
==> (and fun)
- It is an error to request the car or cdr of a null list:
: (car '())
*** ERROR -- PAIR expected
(car '())
: (cdr '())
*** ERROR -- PAIR expected
(cdr '())
- There are also built-in shortcuts which allow you to combine several (up to 4) consecutive cars and cdrs together:
: my-list
==> (cs3 is great (but that is my (dans) opinion) and fun)
: (car (cdr (cdr (cdr my-list))))
==> (but that is my (dans) opinion)
: (cadddr my-list)
==> (but that is my (dans) opinion)
Programming with Lists
- Here are some recursive programs with nested lists
: (define (are-you-a-list l)
(if (null? l) '()
(cons (list? (car l))
(are-you-a-list (cdr l)))))
: (are-you-a-list '(a (b c) () ((d))) )
==> (#f #t #t #t)
- Note what happens when I change cons to list:
: (define (are-you-a-list-broken l)
(if (null? l) '()
(list (list? (car l))
(are-you-a-list-broken (cdr l)))))
: (are-you-a-list-broken '(a (b c) () ((d))) )
==> (#f (#t (#t (#t ()))))
The Truth about Sentences
- They're really a simplification of lists! (and soylent green is made of people!)
- We "watered-down" lists and added constructs from the logo (butfirst, etc) programming language when we first taught you sentences.
Higher-Order Functions
- There are three primary higher-order functions similar to the sentence HOFs which operate on the top-level elements of lists:
- map (similar to every)
- filter (similar to keep)
- reduce (similar to accumulate)
- Examples:
: (define (are-you-a-list-hof l)
(map list? l))
: (are-you-a-list-hof '(a (b c) () ((d))) )
==> (#f #t #t #t)
- We couldn't have done this with sentences for two reasons:
- Sentences can't have nested lists
- The returned list cannot be a sentence because it has booleans in it.
- Filter all the lists and non-lists.
: (filter list? '(a (b c) () ((d))) )
==> ((b c) () ((d)))
: (filter word? '(a (b c) () ((d))) )
==> (a)
- Add a layer of inner parens, and then strip them!
: (map list '(a b c d))
==> ((a) (b) (c) (d))
: (reduce append '((a) (b) (c) (d)) )
==> (a b c d)
Other Primitives for Lists: length, null?, list?, list-ref, equal?, member
length
- Lists also have length which we can query (much like the count of a sentence)
- (length list)
- returns the number of top-level elements in list (ala count)
: (length '(1 2 3 4) )
==> 4
: (length '(a (b c) () ((d))) )
==> 4
: (length '())
==> 0
null?
- When recursing, one often has to test for the null list using the predicate null?
- (null? list)
- returns #t iff list is null, otherwise #f. (ala empty? for sentences)
: (null? '(1 2 3 4) )
==> #f
: (null? '() )
==> #t
list?
- When you've been given something and are wondering whether it is a list...
- returns #t iff list is a list, otherwise #f. (ala sentence? for sentences)
: (list? '(1 2 3 4) )
==> #t
: (list? '() )
==> #t
: (list? 'cs3 )
==> #f
list-ref
- list-ref is like item (for sentences)
- (list-ref list position)
- returns the 0-origin (i.e., starting from 0) element from list specified by position.
: (list-ref '(a b c d) 1)
==> b
: (list-ref '(a b c d) 5)
*** ERROR -- PAIR expected
(list-ref '(a b c d) 5)
: (list-ref '(a (b c) () ((d))) 3)
==> ((d))
: (list-ref '() 0)
*** ERROR -- PAIR expected
(list-ref '(a b c d) 5)
equal?
- equal? works for lists also, and
- (equal? list1 list2)
- returns #t if two lists have the same printed representation.
: (equal? '(a (b c) () ((d))) '(a (b c) () ((d))) )
==> #t
member
- member is like member? (for sentences), except it's a semi-predicate
- (member element list)
- seaches through the top-level elements of list, and when it finds element, returns the part of list starting with element. If it don't find it, it returns #f.
: (member '(b c) '(a (b c) () ((d))) )
==> ((b c) () ((d)))
: (member 'a-new-word '(a (b c) () ((d))) )
==> #f
Example (hard) problem : deep-add-1
- Write deep-add-1, which adds 1 to every number in a complex list of numbers
but keeps the structure
- Requires: every element in the list be a number (i.e., don't worry about error checking for this)
: (deep-add-1 '(1 (2 3) () ((4))) )
==> (2 (3 4) () ((5)))
(define (deep-add-1 L)
Summary
- Sentences are really made of lists
- Lists are a very powerful way of making a collection of anything!
- Unlike sentences, they can contain booleans, procedures, other lists, other sentences, and even a mixed bag of all of these!
In Lab this week you'll see...
- Lists and have your midterm returned to you
In Life this week you'll see...
- The campaigns in their semi-final laps
- More turbulence (and doom and gloom) on Wall Street (what's new?)