SICP 全笔记

Exercise 2.54. Two lists are said to be equal? if they contain equal elements arranged in the same order. For example,

(equal? '(this is a list) '(this is a list))

is true, but

(equal? '(this is a list) '(this (is a) list))

is false. To be more precise, we can define equal? recursively in terms of the basic eq? equality of symbols by saying that a and b are equal? if they are both symbols and the symbols are eq?, or if they are both lists such that (car a) is equal? to (car b) and (cdr a) is equal? to (cdr b). Using this idea, implement equal? as a procedure.

equal? 的比较需要注意两点:

  1. 基本类型
  2. 嵌套表

在写测试用例的时候也需要注意包含这两点。

(define (new-equal? l1 l2)
  (cond ((and (null? l1) (null? l2)) #t)
        ((or (null? l1) (null? l2)) #f)

        ((and (symbol? (car l1)) (symbol? (car l2)))
         (and (eq? (car l1) (car l2))
              (new-equal? (cdr l1) (cdr l2))))

        ((and (number? (car l1)) (number? (car l2)))
         (and (= (car l1) (car l2))
              (new-equal? (cdr l1) (cdr l2))))

        ((and (string? (car l1)) (string? (car l2)))
         (and (string=? (car l1) (car l2))
              (new-equal? (cdr l1) (cdr l2))))

        ((and (pair? (car l1)) (pair? (car l2)))
         (and (new-equal? (car l1) (car l2))
              (new-equal? (cdr l1) (cdr l2))))

        (else #f)))

;;; tests begin
(load "../testframe.scm")

;; test basic type
(let ((lst '(1 2 3 4)))
  (asserteq? (equal? lst lst)
             (new-equal? lst lst)))

(let ((lst '(a b c d)))
  (asserteq? (equal? lst lst)
             (new-equal? lst lst)))

(let ((lst '("a" "b" "c" "d")))
  (asserteq? (equal? lst lst)
             (new-equal? lst lst)))

;; test nested list

(let ((lst '(1 2 3 4 (1 2 3 4 (1 2 3 4)))))
  (asserteq? (equal? lst lst)
             (new-equal? lst lst)))
(let ((lst '(a b c (a b c (a b c)))))
  (asserteq? (equal? lst lst)
             (new-equal? lst lst)))

(let ((lst '("a" "b" ("a" "b" ("a" "b")))))
  (asserteq? (equal? lst lst)
             (new-equal? lst lst)))