;; The first three lines of this file were inserted by DrRacket. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname 2015-10-21-lerner) (read-case-sensitive #t) (teachpacks ((lib "image.rkt" "teachpack" "2htdp") (lib "universe.rkt" "teachpack" "2htdp") (lib "batch-io.rkt" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "image.rkt" "teachpack" "2htdp") (lib "universe.rkt" "teachpack" "2htdp") (lib "batch-io.rkt" "teachpack" "2htdp")) #f)))

;; Given a list of numbers, give me all the numbers greater than 5
;; all>5 : [Listof Number] -> [Listof Number]
(check-expect (all>5 (list 8 6 7 5 3 0 9)) (list 8 6 7 9))
(check-expect (all>5 (list 1 2 3 4)) (list))
(check-expect (all>5 empty) empty)

(define (all>5 lon)
  (cond
    [(empty? lon) empty]
    [(cons? lon) 
     (if (> (first lon) 5)
         (cons (first lon) (all>5 (rest lon)))
         (all>5 (rest lon)))]))

(define (all>6 lon)
  (cond
    [(empty? lon) empty]
    [(cons? lon) 
     (if (> (first lon) 6)
         (cons (first lon) (all>6 (rest lon)))
         (all>6 (rest lon)))]))

(define (all>x lon x)
  (cond
    [(empty? lon) empty]
    [(cons? lon) 
     (if (> (first lon) x)
         (cons (first lon) (all>x (rest lon) x))
         (all>x (rest lon) x))]))


(define (all-even lon)
  (cond
    [(empty? lon) empty]
    [(cons? lon) 
     (if (even? (first lon))
         (cons (first lon) (all-even (rest lon)))
         (all-even (rest lon)))]))


;; A predicate is a function that returns a boolean.

;; filter takes list and a predicate and returns a list of 
;; all the items in the list that satisfy the predicate
;; filter : [Listof X] [X -> Boolean] -> [Listof X]
(define (my-filter lox pred)
  (cond
    [(empty? lox) empty]
    [(cons? lox) 
     (if (pred (first lox))
         (cons (first lox) (my-filter (rest lox) pred))
         (my-filter (rest lox) pred))]))
(define (all-even.v2 lon)
  (my-filter lon even?))

(define (>5 n) (> n 5))
(define (all>5.v2 lon)
  (my-filter lon >5))

(define (all>x.v2 lon x)
  (local ((define (>x n) (> n x)))
    (my-filter lon >x)))
;; EQUIVALENT DEFINITIONS
(define (all>x.v3 lon x)
  (my-filter lon (λ(n) (> n x))))


(all>x.v2 (list 8 6 7 5 3 0 9) 5)




;; length : [Listof X] -> Number
#;(define (length l)
  (cond
    [(empty? l) 0]
    [(cons? l) (add1 (length (rest l)))]))


;; negate : [X -> Boolean] -> [X -> Boolean]
(define (negate.v1 pred)
  (local ((define (opposite v)
            (not (pred v))))
    opposite))
(define (negate.v2 pred)
  (λ(v) (not (pred v))))






(define my-odd? (negate.v2 even?))
(check-expect (my-odd? 5) (not (even? 5)))



(define (count-even l)
  (length (my-filter l even?)))

(define (count-odd l)
  (length (my-filter l (negate.v2 even?))))




;; (map f my-list)
;; (cons a     (cons b     (cons c ...     (cons d     empty) ... )))
;; ==> (map f over this list) produces
;; (cons (f a) (cons (f b) (cons (f c) ... (cons (f d) empty) ... )))
(define (my-map op l)
  (cond
    [(empty? l) empty]
    [(cons? l) (cons (op (first l)) (my-map op (rest l)))]))


;; (cons a (cons b (cons c ... (cons d empty) ... )))
;; ==> (foldr f base over this list) produces
;; (f    a (f    b (f    c ... (f    d base)  ... )))

;; foldr : [X Y -> Y] Y [Listof X] -> Y
(define (my-foldr op base l)
  (cond
    [(empty? l) base]
    [(cons? l) (op (first l) (my-foldr op base (rest l)))]))

(define (sum l)
  (foldr + 0 l))

;; total-string-lengths : [Listof String] -> Number
(define total-string-lengths
  (λ(los)
    (foldr (λ(s n) (+ (string-length s) n)) 0 los)))





(define (adds-1-to l)
  (map add1 l))
(define (adds-2-to l)
  (local ((define (add2 n) (+ n 2)))
    (map add2 l)))
(define (adds-3-to l)
  (map (lambda(n) (+ n 3)) l))


#;(define (foo x y z) body)
;; EQUIVALENT DEFINITIONS
#;(define foo (λ(x y z) body))





((λ(n) (* n n)) 5)