3
votes

I'm trying to understand what count do.

I have read the documentation, and it says:

Returns (length (filter-map proc lst ...)), but without building the intermediate list.

Then, I have read filter-map documentation, and it says:

Returns (filter (lambda (x) x) (map proc lst ...)), but without building the intermediate list.

Then, I have read filter documentation, and I have understand it.

But, I don't understand filter-map. In particular that(lambda (x) x) in (filter (lambda (x) x) (map proc lst ...)).

What is the different between filter and filter-map?

By the way, the examples of filter and filter-map do the same and that make it more difficult to understand them.

2
(filter-map (lambda (x) (if (even? x) (list x x) #f)) '(1 2 3 4 5)) ==> '((2 2) (4 4)).Will Ness

2 Answers

4
votes

I would say that the key insight here is that in the context of filter, you should read (lambda (x) x) as not-false?. So, the documentation for filter-map could be written to read:

Returns (filter not-false? (map proc lst ...)), but without building the intermediate list, where not-false? can be defined as (lambda (x) x).

3
votes

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))))