Search code examples
listschemelispcons

How to return nothing with cons in scheme


I have a small issue with an assigned programming task in Scheme. We were given the task to make a function that returns only the values in a pair structure that meet the requirements of a given predicate. They are also to be returned in the same pair structure, simply with the offending entries removed. So far my code is like follows

(define (keep-if-all ia pred ls)
 (cond
  ((null? ls) null)
  ((pair? ls)
   (cons
    (keep-if-all pred (car ls))
    (keep-if-all pred (cdr ls))))
  ((pred ls) ls)
  (else null)))

The problem is that else returns null and thus replaces the value with null rather than removes it.

For example

(keep-if-all odd? (list 1 2 3 (cons 4 4) (list 1 2 3 4 5)))

returns

(1 () 3 (()) (1 () 3 () 5))

rather than the desired

(1 3 () (1 3 5))

A poke in the right direction would be much appreciated


Solution

  • Just add another if there,

    (define (keep-if-all pred ls)
     (cond
      ((null? ls) '())
      ((pair? ls)
         (let ((x (keep-if-all pred (car ls))))
           (if (or (not (null? x))                ; if something's left of (car ls)
                   .... )                         ;     or if it was a pair,
            (cons x (keep-if-all pred (cdr ls)))  ;   then, include x in the output
            .... )))                              ;   else, don't include x in the output
      ((pred ls) ls)
      (else '())))
    

    Now it works as expected:

    (keep-if-all odd? (list 1 2 3 (cons 4 4) (list 1 2 3 4 5)))
    ;Value 15: (1 3 () (1 3 5))