Index: Some common abstract functions, Sorting
In class you have seen filter:
(define (filter keep? l) (cond [(empty? l) empty] [(cons? l) (cond [(keep? (first l)) (cons (first l) (filter keep? (rest l)))] [else (filter keep? (rest l))])]))
We are familiar with writing functions such as
; double-nums : list-of-number -> list-of-number (define (double-nums a-lon) (cond [(empty? a-lon) empty] [(cons? a-lon) (cons (* 2 (first a-lon)) (double-nums (rest a-lon)))]))
; lessthan3-nums : list-of-number -> list-of-boolean (define (lessthan3-nums a-lon) (cond [(empty? a-lon) empty] [(cons? a-lon) (cons (< (first a-lon) 3) (lessthan3-nums (rest a-lon)))]))
Since these functions are so similar, we'd like to package together the similar parts and separate out the different parts. We'll "package" the similar parts as a new function that can take either of the "different" parts as an argument that tells us what to do:
; map : ?? (see question below) (define (map f l) (cond [(empty? l) empty] [(cons? l) (cons (f (first l)) (map f (rest l)))])) (define (double-num n) (* 2 n)) (define (double-nums a-lon) (map double-num a-lon)) (define (lessthan3-num n) (< n 3)) (define (lessthan3-nums a-lon) (map lessthan3-num a-lon))
We can write the following equation to understand map:
(map f (list x1 ... xN)) = (list (f x1) ... (f xN))
map abstracts the general idea of "computing a new element from each old element and building a list of the new elements" away from what specifically you are computing from each element.
Q: What is the contract for map?
To do: Write double-nums using map and lambda, but without double-num.
We have written many functions to combine elements of a list, e.g., to sum the numbers in a list and to find the maximum element in a list. There are two versions of folding that prove to be very useful. Equationally, we can write
(foldr f base (list x1 x2 ... xN)) = (f x1 (f x2 ... (f xN base))) (foldl f base (list x1 x2 ... xN)) = (f xN ... (f x2 (f x1 base))...)Note how the two versions combine the elements of the input list in opposite order. Both are built-in to Scheme.
Q: Based upon these equations, what should the following produce?
(foldr cons empty (list -1 5 -3 4 2)) (foldl cons empty (list -1 5 -3 4 2))
To do: Define the function foldr to satisfy the above equation. It follows the template for a function consuming a list.
To do: Using foldr, define functions to compute
Q:
For the curious...
The following two functions implement one algorithm for sorting a list of numbers.
; insert<-num : number list-of-number (number number -> boolean) -> list-of-number ; assumes the input list is sorted non-descending ; returns a new sorted non-descending list with the input number in it (define (insert<-num n a-lon) (cond [(empty? a-lon) (cons n empty)] [(cons? a-lon) (cond [(< n (first a-lon)) (cons n a-lon)] [else (cons (first a-lon) (insert<-num n (rest a-lon)))])])) ; isort<-nums : list-of-number -> list-of-number ; returns a new sorted non-descending version of the input list (define (isort<-nums a-lon) (cond [(empty? a-lon) empty] [(cons? a-lon) (insert<-num (first a-lon) (isort<-nums (rest a-lon))))))For example
(insert<-num 3 empty) = (list 3) (insert<-num 1 (list 3 4 7)) = (list 1 3 4 7) (insert<-num 3 (list 1 4 7)) = (list 1 3 4 7) (insert<-num 7 (list 1 3 4)) = (list 1 3 4 7) (isort<-nums empty) = empty (isort<-nums (list 7 1 4 3)) = (list 1 3 4 7)
The above code only sorts numbers in non-descending order (because of the test <). To do: