#lang racket

;; (all-ok? ok? lst) return #t if ok? is true of
;;   every element of lst
;; Pre: lst is a list
;;      ok? is a predicate procedure applicable to 
;;           every element of lst
(define all-ok?
  (lambda (ok? lst)
    (if (empty? lst)
        #t
        (and (ok? (first lst))
             (all-ok? ok? (rest lst))))))




;; (all-odd? lst) return #t if every element of lst is odd
;; Pre: lst is a list of numbers.
(define all-odd?
  (lambda (lst)
    (if (empty? lst) 
        #t
        (and (odd? (first lst)) 
             (all-odd? (rest lst))))))

;; (all-even? lst) return #t if every element of lst is even
;; Pre: lst is a list of numbers.
(define all-even?
  (lambda (lst)
    (if (empty? lst)
        #t
        (and (even? (first lst)) 
             (all-even? (rest lst))))))

(all-odd? '(1 3 5 7))
(all-odd? '(1 3 2 7))

(all-even? '(2 4))
(all-even? '(2 4 5))

;; (inc x) return x+1
;; Pre: x is a number.
(define inc
  (lambda (x) 
    (+ x 1)))
    
;; (make-proc f g) return a composition g(f(x))
;; Pre: f and g are procedures, such that the 
;;      composition g(f(x)) is well-defined.
(define make-proc
  (lambda (f g)
    (lambda (x)
      (g (f x)))))

((make-proc inc inc) 42)
((make-proc inc (lambda (x) (* x 2))) 42)



;;Mutual recursion example
(define even (lambda (lst)
  (cond
    ((empty? lst) empty)
    (else (cons (first lst) (odd (rest lst)))))))

(define odd (lambda (lst)
  (cond
    ((empty? lst) empty)
    (else (even (rest lst))))))


;; what if I want to define a function with a variable arity? - sum of squares
;; Not tail recursive, or terribly good style
;;
;; Sum of the squares of all input values - version 1, fixed from class
;; Note the use of eval and quote/'. We can discuss this in class if you want.
;; Key in our discussion of representing functions as symbols
(define sum-squares1
  (lambda lst
    (if (empty? lst) 0
        (+ (* (first lst)(first lst))
           (eval (cons 'sum-squares1 (rest lst)))))))


;; Version which also uses map - will go over on Monday
(define sumsquare (lambda args (eval (cons '+ (map * args args)))))


