Lecture 15: Some Functions are Chameleons; Some Data Definitions, too

###
Lecture 15: Some Functions are Chameleons; Some Data Definitions, too

1. Parameterized data definitions:

       			    A list-of-XYZs is either
       			     - empty or
       			     - (cons N L)
       				 where N is a XYZ
       				 and L is a list-of-XYZs.

   We write `(listof XYZ)` from now on. XYZ is a placeholder, but unlike those in programs it stands for entire collections of data, not just individual pieces of data.

   Examples:

   - (listof number) :
     (list 1 2 3)
     (list -1 -2 -3)
   - (listof symbol) :
     (list 'a 'b 'c)
     (list 'eve 'adam)
   - (listof pr) where ps is a structure: (make-personnel-record symbol number):

           (list (make-personnel-record 'Man 100000)
                 (make-personnel-record 'Kiddo 1000))

2. What's the contract of blah?

       (define (blah alon num sign)
         (cond
           ((empty? alon) num)
           (else (sign (first alon) (blah (rest alon))))))

   To answer this question, we must step back and ask:

   What are the rules of the game?

   Function names and primitive operations are values. That is, if Scheme provides `prim-op` and we define `(define (f ... ) ...)` in our program (scope), then `prim-op` and `f` are values just like `5, 'eve, #t`.

   What is the data definition of such a value?
   When we say number, we know we are talking about `5, -5, 3/4 or #i1.789` etc.
   When we say symbol, we know we are talking about `'eve, 'adam` etc.
   When we say (listof symbol), we know we are talking about `(cons 'eve (cons 'adam empty))` etc.

   But what about things like `+`? Or `not`? To what data collection to they belong?
   + is an operation that consumes two numbers and produces their sum: (number number -> number)
   How about

       (define (f x y)
         (/ (+ x y)
            2))

   f is a function that consumes two numbers and produces their sum: (number number -> number)
   How about

       (define (g x)
         x)

   g is a function that consumes a number and returns it: (number -> number)
   But we can also think of it as a function that consumes a symbol and returns it: (symbol -> symbol)

   In general, a function/an operation belongs to a class of data that is best described with our arrow notation:

   `(A ... B -> C)`
   functions that consume data of class A ... B and produce C.
3. Let's slowly work our way up to blah's contract:
   - the (re)definition of `pi, sum, largest, smallest` suggests:
     `(listof number) number (number number -> number) -> number`
   - the definition of `demands-going-up, demands-going-down` suggests:
     `(listof number) (listof PR) (number (listof number) -> (listof number)) -> (listof number)`
   - the definition of `project` suggests:
     `(listof PR) (listof PR) (PR (listof PR) -> (listof PR)) -> (listof PR)`

   Here we go: we need placeholder in contracts, too:

   `(listof X) Y (X Y -> Y) -> Y`

   What do X and Y stand for in the above sample contracts? Data collections again. If we want a "concrete" contract, we must replace all X with some "specific" collection and all Y with another one (or the same).

   This is called parametric polymorphism

Matthias Felleisen | This page was generated on Fri Mar 5 09:04:41 CST 1999.