Lecture 10, July 10

The lecture notes I post serve two purposes: to remind you of the topics we discussed and to provide any interesting code examples I did during lecture. I would describe these notes as an outline, not a summary, of what I talked about during lecture. You are not expected to be able to learn the material simply from examining these notes, nor is reading these notes a reasonable substitute for attending lecture.

Lambda

Lambdas can be used to create function values without defining variables to refer to those functions.

Match

Patterns can have several forms:

Family Tree

; Person has Name, Year of Birth, Father, Mother

(define-struct None ())
(define-struct Person
  ([name : String]
   [yob : Integer]
   [father : FT]
   [mother : FT]))
(define-type FT (U None Person))

(define test-tree
  (Person "Alice" 2000
          (Person "Bob" 1970
                  (Person "Daniel" 1940 (None) (None))
                  (None))
          (Person "Claire" 1965 (None) (None))))

; generations outputs number of generations in a FT
(: generations : FT -> Nonnegative-Integer)
(define (generations t)
  (match t
    [(None) 0]
    [(Person _ _ f m) (+ 1 (max (generations f)
                                (generations m)))]))
(define (generations t)
  (cond
    [(None? t) 0]
    [else (+ 1 (max (generations (Person-father t))
                    (generations (Person-mother t))))]))


; count-people outputs the total number of people in a FT
(: count-people : FT -> Nonnegative-Integer)
(define (count-people t)
  (match t
    [(None) 0]
    [(Person _ _ f m) (+ (count-people f)
                         (count-people m) 1)]))

; find takes a FT and a string as inputs.  The output is true
; if there is a person in the tree with a name that matches the input string.
; False otherwise
; Example (find test-tree "Bob") -> true
;         (find test-tree "Evelyn") -> false
(: find : FT String -> Boolean)
(define (find t name)
  (match t
    [(None) false]
    [(Person (? (λ ([s : String]) (string=? s name))) _ _ _) true]
    [(Person _ _ f m) (or (find f name)
                          (find m name))]))
(define (find t name)
  (match t
    [(None) false]
    [(Person s _ f m) (or (string=? s name)
                          (find f name)
                          (find m name))]))
; Both these solutions for find are okay.  I think the second one is better style.
; The first one is interesting because it uses lambda and the match predicate,
; both of which you should try to practice before the next quiz.

; num-unknowns outputs total number of unknown ancestors in tree
; This is the number of (None) structures in the tree
; Example (num-unknowns test-tree) -> 5
(: num-unknowns : FT -> Nonnegative-Integer)
(define (num-unknowns t)
  (match t
    [(None) 1]
    [(Person _ _ f m) (+ (num-unknowns f)
                         (num-unknowns m))]))