;;; File:
;;;   exam2-utils.ss
;;; Author:
;;;   Samuel A. Rebelsky
;;; Summary:
;;;   Sample procedures for exam 2.
;;; Contents:
;;;   (compose f g)
;;;     Function composition
;;;   (left-section binproc val1)
;;;     Create a unary procedure by filling in the left (first)
;;;     argument to binproc with val1.
;;;   (right-section binproc val2)
;;;     Create a unary procedure by filling in the right (second)
;;;     argument to binproc with val2.
;;;   (tally pred? lst)
;;;     Count the number of values in lst for which pred? holds.

;;; Procedure:
;;;   compose
;;; Parameters:
;;;   f, a unary function
;;;   g, a unary function
;;; Purpose:
;;;   Functionally compose f and g.
;;; Produces:
;;;   fun, a unary function.
;;; Preconditions:
;;;   f can be applied to any values g generates.
;;; Postconditions:
;;;   fun can be applied to any values g can be applied to.
;;;   fun generates values of the type that f generates.
;;;   (fun x) = (f (g x))
(define compose
  (lambda (f g) ; Parameters to compose
    ; Build a procedure of one parameter
    (lambda (x)
      ; Apply g to x and then apply f to the result.
      (f (g x)))))

;;; Procedure:
;;;   left-section
;;; Parameters:
;;;   binproc, a procedure of two parameters
;;;   val1, a value
;;; Purpose:
;;;   Creates a new unary procedure by filling in the first
;;;   parameter of binproc.
;;; Produces:
;;;   newproc, a procedure of one parameter.
;;; Preconditions:
;;;   val1 is of an appropriate type for the first parameter
;;;     to binproc.
;;; Postconditions:
;;;   newproc's parameter must be of the same type as the first
;;;     parameter to binproc.
;;;   (newproc val2) equals (binproc val1 val2)
(define left-section
  (lambda (binproc val1)  ; Parameters to left-section
    (lambda (val2)        ; Parameters to newproc
      (binproc val1 val2))))

;;; Procedure:
;;;   right-section
;;; Parameters:
;;;   binproc, a procedure of two parameters
;;;   val2, a value
;;; Purpose:
;;;   Creates a new unary procedure by filling in the second
;;;   parameter of binproc.
;;; Produces:
;;;   newproc, a procedure of one parameter.
;;; Preconditions:
;;;   val2 is of an appropriate type for the second parameter
;;;     to binproc.
;;; Postconditions:
;;;   newproc's parameter must be of the same type as the first
;;;     parameter to binproc.
;;;   (newproc val1) equals (binproc val1 val2)
(define right-section
  (lambda (binproc val2)  ; Parameters to right-section
    (lambda (val1)        ; Parameters to newproc
      (binproc val1 val2))))

;;; Procedure:
;;;   tally
;;; Parameters:
;;;   pred?, a unary predicate
;;;   lst, a list of values
;;; Purpose:
;;;   Counts all values in lst for which pred? holds.
;;; Produces:
;;;   count, an integer
;;; Preconditions:
;;;   pred? must be applicable to all the values in lst. [Unverified]
;;; Postconditions:
;;;   lst contains exactly count values for which pred? returns
;;;     a value other than false.
(define tally
  (lambda (pred? lst)
    (cond
      ; If the list is empty, no values match.
      ((null? lst) 0)
      ; If the first value matches, count it
      ((pred? (car lst)) (+ 1 (tally pred? (cdr lst))))
      ; Otherwise, count the remaining values
      (else (tally pred? (cdr lst))))))
