TOPIC: list structures

Lists are incredibly useful objects.  
* Ordered sequences of stuff
    - have first, second, etc. elements.  
* Length isn't restricted.
Here's the abstraction:CONSTRUCTOR: 
  * cons  <object>,<list> --> <list>      
--- add an element to a list.

SELECTORS:  
* head  <list> --> <object>  
* tail  <list> --> <list>  
* null?  <list>  --> <boolean>CONTRACT:  (head (cons x l)) = x
  (tail  (cons x l)) = l
  (null? l) = #t  IFF l is the empty-list, which is written '() and prints as ()
  >> Yes, that is an unmatched single quote, [which will see more
     in recitation].   Lots more coming. Note that we don't say what 
  (head '()) and   (tail '())  are  * So, we DON'T use them.
---------------------------------------------------------------------
Lists in Dylan are built out of pairs, and there is a concrete implementation,
so There are thus THREE ways that cons/head/tail are used:  * "Proper" lists
  * pairs  * structures combining the twoIMPORTANT FACTS:
  * If L is a nonempty proper list, (tail L) MUST be a proper list.
  * (tail '()) is undefined.
  * A proper list is built by consing elements onto a proper list.
      * Repeated TAIL eventaully gives you '()?  PROPER
      * Repeated TAIL eventually gives you an "atom" (something not a <pair>)
                 IMPROPER

Two types in Dylan
<pair>, anything that can be taken apart with head/tail
<list>, <pair> plus the empty list ()

Note that the types <list> and <pair> do not correspond to the notions 
of proper or improper lists.(define (a <pair>) (cons 1 2))  or <list> 
 
 
THIS IS NOT A PROPER LIST, because its tail is not a list.  (tail a) is 2
(define (b <list>) (cons 1 (cons 2 (cons 3 '()))))  or <pair> 

  
THIS IS A PROPER LIST:   () is a proper list   so (cons 3 '()) is   ...
   so b is, too.>> Draw box-and-pointer diagram.

IMPORTANT FACT: [useful on prelims!]  * Cons always builds exactly ONE box.
Note that in a box and pointer diagram, a pointer points to an ENTIRE box, 
not (e.g. the front half).  A box is 

---------------------------------------------------------------------
b will print as (1 2 3)
Note that this looks a whole lot like Dylan expressions.    

* It's intentional
  
* We'll be writing Dylan programs which manipulate Dylan
    expressions.  We'll be doing this in PS#3 and PS#6.
  

* This is why we teach in a language with uniform syntax like Dylan.
---------------------------------------------------------------------

There are lots of useful operations on lists.
LIST is a procedure which puts its arguments into a proper list
(list + 27 (+ 2 1))  --> ({add} {27} {3})

LIST isn't a special form, so all its arguments are evaluated!
[It is kind of funky, in that it takes any number of arguments.]

We're going to be building Dylan code.  What if we want to build thelist 
  (+ 27 3)?We want to TURN OFF the evaluator temporarily.

This isn't just an issue with programming languages.Compare:  "Say your name"
with   "Say 'your name'"


We use a form of QUOTATION to tell the interpreter, "don't eval this".

Have seen this on symbols:  'STUFF  
means, "just return something that prints like STUFF as a value"  + ----> {add} 
  '+ ---> +        <<-- The <symbol> +  x ----> depends 
  'x ---> x        <<-- The <symbol> x  (+ 1 2) ---> 3
  '(+ 1 2)  ---> a list of three elements, which prints as (+ 1 2)  

This helps our immediate problem:  (list '+ 1 2) ---> (+ 1 2)Note: 
(bind (((a <integer> 3)))
  (list '+ a 2))  ---> (+ 3 2) [list isn't a special form!]       


The elements of a list can be ANYTHING:  * including lists and pairs.
(list '* (list '+ 1 2) 3) looks like this:   >> Draw the boxesIt prints as 
   (* (+ 1 2) 3)It's a list of THREE ELEMENTS,
  -- Second element is itself a LIST OF THREE ELEMENTS.

IMPORTANT FACT: [useful on prelims!]
  * LIST called with N arguments builds exactly N boxes.
---------------------------------------------------------------------
Let's do some useful things with lists. 
Computing the length (number of elements) is one of the most basic
operations on a list.  This is a Dylan primitive, but lets see how it
can be implemented:(define (length <function>)  (method ((l <list>))

    (if (null? l)        0        (+ 1 (length (tail l))))))

>> What kind of process?  Recursive! <<[Can you write a tail-recursive version?]

[How would you prove it correct?  We'll get to that](length '(1 2 3))     == 3
(length '(1 (2 3) 4)) == 3  

* Just the number of elements in the top-level list
  
* count how many tail's there are 'til we get to the empty list.NOTE:
  
* This is a non- O(1) primitive!  ... What is its order of growth?
   CAVEAT EMPTOR!
---------------------------------------------------------------------
Very often, you want to apply a function to each element of a list and
return a new list as a result.
  (map f list) applies f to every element of list, returns result  VERY POWERFUL

This is a Dylan primitive, but lets see how to implement it:
(define (map <function>)  (method ((f <function>) (l <list>))    (if (null? l)
        '()        (cons (f (head l))              (map f (tail l))))))
  * go down the list taking successive tail's
  * cons up -- or build -- the resulting list.

Like length, map operates element-by-element, not on the primitiveelements:
(map length '(1 (2 3) (4 5 6) 7)) ==> (1 2 3 1)
NOTE: map is *also* a non- O(1) primitive.  What is its order of      growth?
---------------------------------------------------------------------
NOTE: map in Dylan can walk down several lists simultaneously.
(map + '(1 2 3) '(5 6 7)) ==> (6 8 10)
---------------------------------------------------------------------
(define (copy <function>)  (method ((l <list>))
    (map (method ((x <object>)) x) l)))
(copy '(1 2 3)) ==> (1 2 3), but it's a different list with differentboxes. 
id? is a version of equality that tells if two pairs are the same box.
  * It'll be important later on.(id? l l) ---> always true.
(id? l (copy l)) ---> always false.  prints the same, but different list.
---------------------------------------------------------------------