#lang scheme #| A list is either: empty list a first element and the rest of the list |# #| Length of list l. |# (define list-length (lambda (l) (if (empty? l) 0 (+ 1 (list-length (rest l)))))) (define #| Implicit precondition "list l", so only need to test lists |# #| Test with extreme/boundary cases: empty, 1 element |# (display (equal? (list-length '()) 0)) ; ... #| Test with non-extreme/boundary case |# (display (equal? (list-length '(a b c)) 3)) #| Whether unary f called on each element in input, a list of acceptable arguments for f, produces the corresponding elements of expected-results, a list of the same length as inputs. |# (define tester (lambda (f inputs expected-results) #;(if (empty? inputs) #t (and (equal? (f (first inputs)) (first expected-results)) (tester f (rest inputs) (rest expected-results)))) (or (empty? inputs) (and (equal? (f (first inputs)) (first expected-results)) (tester f (rest inputs) (rest expected-results)))))) (tester list-length '(() (x) (a b c)) '(0 1 3)) (tester list-length '(() a) '(2 0)) ; tester needs more testing #| List of the inputs that when f is called on them don't produce the corresponding elements of expected-results. Precondition: f a function of one argument (unary function) inputs a list of acceptable arguments for f (i.e. satisfying f's precondition) expected-results a list the same length as inputs |# (require scheme/local) (define failed-tests (lambda (f inputs expected-results) (if (empty? inputs) '() (local [(define failed-tests-rest (failed-tests f (rest inputs) (rest expected-results)))] (if (equal? (f (first inputs)) (first expected-results)) failed-tests-rest (cons (first inputs) failed-tests-rest)))))) (failed-tests list-length '(() () (x) (y) (a b c) (d e f)) '(0 1 0 1 3 2))