Not return anything from LISP/Scheme
functional-programming, lisp, map-function, racket, scheme
Solution
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)
Problem
Basically, I would like to use map to do selection in a list like ``` (define tbl '(a b c d)) (map (lambda (item 'c) (if (eq? item 'c) item (...what in else?) ))) ``` The result I want is ``` '(c) ``` I tried leave the else part empty, it complains that the else part is needed. I tried ``` (display "foo") ``` as else part and got ``` (#<void> #<void> c #<void>) ``` That is close. Is there any way that I can use map to get '(c)? I know the recursive way, but I am wondering if map can do it as well. If not '(c), at least (# # c #) but not using the display hack to achieve a void type return value.