You want to use filter
, not map
- because the output list will potentially have less elements than the input list. All those #<void>
values returned by display
are there because map
will always include a result in the output list, even for those elements we're not interested in.
(define tbl '(a b c d))
(filter (lambda (item) (eq? item 'c)) tbl)
=> '(c)
Equivalently, and a bit shorter:
(filter (curry eq? 'c) tbl)
=> '(c)
map
is used when you want to do something to each of the elements in the input list, without discarding elements. On the other hand, filter
is used for selecting some of the elements in the input list, those that evaluate to #t
for a given predicate, and filter
is available in most Scheme interpreters, if it's not available you can import SRFI-1
or use the reference implementation.
There's no way to obtain '(c)
using only map
(it can be hacked using map
plus apply
or remove*
, etc. but that's not the idea, is it?); if for some reason you have to use only map
and don't mind returning a list with placeholders, here are a couple of alternatives:
(map (lambda (item) (if (eq? item 'c) item '%)) tbl) ; placeholder in else part
=> '(% % c %)
(map (lambda (item) (when (eq? item 'c) item)) tbl) ; when has implicit #<void>
=> '(#<void> #<void> c #<void>)
Time for a little hacking. Using map
plus apply
(as explained in @WillNess' answer), this has the advantage of working in any RxRS interpreter and is the most portable solution, because it uses standard procedures:
(apply append (map (lambda (item) (if (eq? item 'c) (list item) '())) tbl))
=> '(c)
Using map
plus remove*
:
(remove* (list (void)) (map (lambda (item) (when (eq? item 'c) item)) tbl))
=> '(c)
For a change, a solution without map
- using foldr
instead:
(foldr (lambda (item a) (append (if (eq? item 'c) (list item) '()) a)) '() tbl)
=> '(c)
Of course, you can always implement your own version of filter
using only standard procedures, this will also be portable across all RxRS interpreters:
(define (filter pred? lst)
(cond ((null? lst)
'())
((not (pred? (car lst)))
(filter pred? (cdr lst)))
(else
(cons (car lst)
(filter pred? (cdr lst))))))
(filter (lambda (item) (eq? item 'c)) tbl)
=> '(c)