4
votes

I wrote a big program that use car and cdr, and do:

(map car (append (map caddr lists) (map cadr lists))

When lists is list of lists in the next format ((a (b) (c)) (d (e) (f))...(x (y) (z))) When I did it I got one list (b c e f... y z) (Note: b,c,...y,z is a list of numbers; a,d...x is a symbol)

But now, I found that b,c,...,y,z can be also empty list, and It gives the next error:

car: expects argument of type <pair>; given ()

What can I do?

2
So what do you want it to do if (b c ...) is empty? Return the empty list?Shaun
@shaun: Nothing. I dont need them in (b c....). I try to delete the empty list, but it didn't succssed.Adam Sh

2 Answers

2
votes

Have you tried filtering away empty lists before your map? Something like this:

(map car (filter pair? (append (map caddr lists) (map cadr lists))))

The fundamental issue is that () is not a pair while car only acts on pairs. The simplest solution is just to get rid of everything that isn't a pair before mapping car onto the list; this is what (filter pair? ...) does.

1
votes

Here's my shot. It's a straight solution, without using map, filter; in that way, I avoid going over and over the elements of the list constructing intermediate lists - except that I used a reverse operation for preserving the original order of the elements, if that's not an issue, remove reverse. For each element in the original list, if either the (b)... or (c)... part is empty, it's skipped.

(define (process lists)
  (let loop ((l (reverse lists))
             (a '())
             (b '()))
    (cond ((null? l)
           (append b a))
          ((or (not (pair? (cadar l))) (not (pair? (caddar l))))
           (loop (cdr l) a b))
          (else
           (loop (cdr l) (cons (caadar l) a) (cons (car (caddar l)) b))))))