Question

I'm going through the "Little Schemer" book, and doing the various functions. Generally I end up with the same version as the books, but not for eqlist?, which is a function to test the equality of two lists.

I've tried testing my version and it passes anything I throw at it. Yet it's slightly different from the "Little Schemer" version, and I'd like someone's opinion on whether I'm missing something - I suspect that's the case.

My version:

(define eqlist?
  (lambda (list1 list2)
    (cond
      ((and (null? list1)(null? list2))#t)
      ((or (null? list1)(null? list2))#f)
      ((and (atom? list1)(atom? list2))(eqan? list1 list2))
      ((or (atom? list1)(atom? list2)) #f)
      (else
        (and(eqlist? (car list1) (car list2))
            (eqlist? (cdr list1) (cdr list2)))))))

The book's version:

(define eqlist2? ;This is Little Schemer's version
  (lambda (list1 list2)
    (cond
      ((and (null? list1)(null? list2)) #t)
      ((or (null? list1)(null? list2)) #f)
      ((and (atom? (car list1))(atom? (car list2)))
       (and (eqan? (car list1)(car list2))(eqlist2? (cdr list1)(cdr list2))))
      ((or (atom? (car list1))(atom? (car list2))) #f)
      (else
       (and (eqlist2? (car list1)(car list2))
            (eqlist2? (cdr list1)(cdr list2)))))))

And in both cases the definition of eqan is:

(define eqan?
  (lambda (a1 a2)
    (cond
      ((and (number? a1)(number? a2)) (equal? a1 a2))
      ((or (number? a1)(number? a2)) #f)
      (else (eq? a1 a2)))))

Thank you!

Joss Delage

Was it helpful?

Solution

The book version would break if passed in an atom or an improper list (a pair which is not a list -- something like (1 2 . 3)) as an argument. (Note it does work with '(), of course -- not sure if TLS considers this to be an atom or not.) This makes your function actually more robust, though possibly better named eqv? / equal? than eqlist?. (I see equal? is used in eqan? to test numeric equality, but traditionally this name is attached to a universal value equality testing function.)

Basically, your eqlist? works on any type of arguments under the assumptions that (1) atom? is able to tell pairs (things with car and cdr) from non-pairs (it's the negated version of pair?), (2) eqan? tests the equality of atoms, (3) everything is either '() or a pair or an atom. (Well, actually '() is an atom in my eyes -- and Petite Chez Scheme agrees.) The book version works on proper lists (including '()), makes similar assumptions and disregards the possibility of encountering an improper list.

I wouldn't be surprised if a more robust equality testing function was presented later on in the book, but I don't have it available to check. Anyway, the book version of eqlist? you posted seems like something meant to illustrate the basic ideas behind lists, not something you'd actually want to use in day-to-day programming. In fact, the given version of eqan? would break in an unrestricted environment where there's more atomic types of data to consider, among which at the very least strings would need to be accounted for separately, thus invalidating the assumptions listed in the second paragraph above and breaking both versions of eqlist?.

OTHER TIPS

here is my version:

(define eqlist?
    (lambda (l1 l2)
      (cond
        ((and (null? l1) (null? l2))
         #t)
        ((and (atom? (car l1)) (atom? (car l2)))
         (and (eq? (car l1) (car l2)) (eqlist? (cdr l1) (cdr l2))))
        (else
         (and (eqlist? (car l1) (car l2)) (eqlist? (cdr l1) (cdr l2)))))))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top