The whole point is that if you know filter
and map
well, then you can explain filter-map
like that. If you do not know what filter
and map
does it will not help you understand it. When you need to learn something new you often need to use prior experience. Eg. I can explain multiplication by saying 3 * 4
is the same as 3 + 3 + 3 + 3
, but it doesn't help if you don't know what +
is.
What is the difference between filter
and filter-map
(filter odd? '(1 2 3 4 5)) ; ==> (1 3 5)
(filter-map odd? '(1 2 3 4 5)) ; ==> (#t #t #t))
The first collects the original values from the list when the predicate became truthy. In this case (odd? 1)
is true and thus 1
is an element in the result.
filter-map
doesn't filter on odd?
it works as if you passed odd?
to map
. There you get a new list with the results.
(map odd? '(1 2 3 4 5)) ; ==> (#t #f #t #f #t #f)
Then it removes the false values so that you only have true values left:
(filter identity (map odd? '(1 2 3 4 5))) ; ==> (#t #t #t)
Now. It's important to understand that in Scheme every value except #f
is true.
(lambda (x) x)
is the identity function and is the same as identity
in #lang racket
. It returns its own argument.
(filter identity '(1 #f 2 #f 3)) ; ==> (1 2 3)
count
works the same way as filter-map
except it only returns how many element you would have got. Thus:
(count odd? '(1 2 3 4 5)) ; ==> 3
Now it mentions that it is the same as:
(length (filter identity (map odd? '(1 2 3 4 5)))
Execpt for the fact that the the code using map
, filter
, and length
like that creates 2 lists. Thus while count does the same it does it without using map
and filter
. Now it seems this is a primitive, but you could do it like this:
(define (count fn lst)
(let loop ((lst lst) (cnt 0))
(cond ((null? lst) cnt)
((fn (car lst)) (loop (cdr lst) (add1 cnt)))
(else (loop (cdr lst) cnt))))
(filter-map (lambda (x) (if (even? x) (list x x) #f)) '(1 2 3 4 5))
==>'((2 2) (4 4))
. – Will Ness