;;; Procedure:
;;;   sequential-search-list
;;; Parameters:
;;;   pred?, predicate
;;;   lst, a list
;;; Purpose:
;;;   Searches the list for a value that matches the predicate.
;;; Produces:
;;;   match, a value
;;; Preconditions:
;;;   pred? can be applied to all values in lst.
;;; Postconditions:
;;;   If lst contains an element for which pred? holds, match
;;;     is one such value.
;;;   If lst contains no elements for which pred? holds, match
;;;     is false (#f).
(define sequential-search-list
  (lambda (pred? lst)
    (cond
      ; If the list is empty, no values match the predicate.
      ((null? lst) #f)
      ; If the predicate holds on the first value, use that one.
      ((pred? (car lst)) (car lst))
      ; Otherwise, look at the rest of the list
      (else (sequential-search-list pred? (cdr lst))))))

;Welcome to DrScheme, version 201.
;Language: Graphical (MrEd, includes MzScheme).
;> (sequential-search-list even? (list 1 3 5 2 5))
;2
;> (sequential-search-list even? (list 1 3 5 5))
;#f
;> ; How do we search for the number 5?
;(define 5? 
;  (lambda (val) (if (= 5 val) #t #f)))
;> (5? 2)
;#f
;> (sequential-search-list 5? (list 2 3 1 4 12))
;#f
;> (sequential-search-list 5? (list 2 3 4 1 5))
;5
;> ; How do we search for the number 5?
;(define 5? 
;  (lambda (val) (= 5 val)))
;> (sequential-search-list 5? (list 2 3 4 1 5))
;5
;> (define silly
;    (lambda (val) (if val #t #f)))
;> (silly #t)
;#t
;> (silly #f)
;#f
;> (if (= 5 3) #t #f)
;#f
;> ; How do we search for the number 5?
;(define 5? 
;  (lambda (val) (= 5 val)))
;> ; How do we ask if a number is greater than 3?
;(define >3?
;  (lambda (val) (> val 3)))
;> (>3? 2)
;#f
;> (>3? 4)
;#t
;> (>3? 3)
;#f
;> (define numbers (list 3 2 1 5 2 3))
;> numbers
;(3 2 1 5 2 3)
;> (sequential-search-list >3? numbers)
;5
;> (define numbers (list 3 2 1 5 2 45 3))
;> (sequential-search-list >3? numbers)
;5
;> (sequential-search-list >3? (list 3 2 1 5 2 45 3))
;5
;> (sequential-search-list? (lambda (x) (> 3 x)) numbers)
;. reference to undefined identifier: sequential-search-list?
;> (sequential-search-list (lambda (x) (> 3 x)) numbers)
;2
;> (sequential-search-list (lambda (x) (> x 3)) numbers)
;5
;> (sequential-search-list (let ((>3? (lambda (x) (> x 3)))) >3?)
;                          numbers)
;5

(define sidekicks
  (list
   (list "Asterix" "Obelix")
   (list "Obelix" "Dogmatix")
   (list "Fred Flinstone" "Barney Rubble")
   (list "Quick Draw McGraw" "Baba Looey")
   ))

;> ; What is the hero/sidekick list whose hero is "Asterix"?
;(sequential-search-list (lambda (x) (equal? "Asterix" x))
;                        sidekicks)
;#f
;> (sequential-search-list (lambda (x) (equal? "Asterix" (car x)))
;                          sidekicks)
;("Asterix" "Obelix")
;> (sequential-search-list (lambda (x) (equal? "Quick Draw McGraw" (car x)))
;      
;                          sidekicks)
;("Quick Draw McGraw" "Baba Looey")
;> (cadr
;   (sequential-search-list (lambda (x) (equal? "Asterix" (car x)))
;                          sidekicks))
;"Obelix"
;> ; What is the hero/sidekick list whose sidekick is "Barney Rubble"?
;(sequential-search-list (lambda (x)
;                          (equal? "Barney Rubble"
;                                  (cadr x)))
;                        sidekicks)
;("Fred Flinstone" "Barney Rubble")

; The following procedure tries to encapsulate what we did
; in those:
;   Look for sidekick "Barney Rubble" noting that sidekicks
;   are the cadr of each entry
;  The thing to look for is the *key*
;  The place to look in each entry is the *get-key*
(define search-list-for-keyed-value
  (lambda (key lst get-key)
    (sequential-search-list (lambda (x)
                              (equal? key
                                      (get-key x)))
                            lst)))

;> (search-list-for-keyed-value "Asterix" sidekicks car)
;("Asterix" "Obelix")
;> (search-list-for-keyed-value "Obelix" sidekicks car)
;("Obelix" "Dogmatix")
;> (search-list-for-keyed-value "Obelix" sidekicks cadr)
;("Asterix" "Obelix")