Related material in How to Design Programs: part iv
to abstract over recurring patterns in functions, why it matters
the design recipe
recognize patterns in two functions: circle the differences and connect them with lines in the two definitions;
for each pair of differences, introduce a new parameter and use it in place of the circled deltas;
define each of the old functions in terms of the abstraction and use the old test suite to ensure that things still work.
What’s the difference?
;; | ;; |
Doing better:1
;; |
;; | ;; |
;; | ;; |
;; |
(define (smaller pivot l) (extract pivot l <)) ;; test: (equal? (smaller 3 (list 1 2 3 4 5)) (list 1 2)) | (define (larger pivot l) (extract pivot l >)) ;; test: (equal? (larger 3 (list 1 2 3 4 5)) (list 4 5)) |
;; | ;; |
;; |
(define (xxxs gl) (every gl one-gpa)) | (define (remove-all-green cl) (every cl remove-green)) |
Posn
s.
A list-of-GradeRs is either
- empty
- (cons n l)
where n is a GradeR
and n is a list-of-GradeRs.A list-of-Colors is either
- empty
- (cons n l)
where n is a Color
and n is a list-of-Colors.
Use (Listof X) instead.
We have:
;;tax: Number → Number
;;xxxs: PosnList → NumberList
;;draw-ufo : Posn → true
So it’s not surprising that:
;;draw-solid-disk : Posn Number ColorSymbol → true
;;< : Number Number → Boolean
;;remove-green : Color → Color
;;one-gpa : GradeR → GPA
And therefore:
;;dc-ufo : Posn (Posn Number ColorSymbol → true) → true
;;extract : NumberList (Number Number → Boolean) → NumberList
But what about every
? (Listof X) (X → Y) → (Listof Y)
1 There is a different alternative.