Nyquist / XLISP 2.0 - Contents | Tutorials | Examples | Reference

# cl:equalp

(equalp expr1 expr2)
  exprN - arbitrary Lisp expressions
  returns - T if the expressions are structurally equal, NIL otherwise

Two expressions are 'equalp':

- If the expressions are equal.

- If two numbers of arbitrary type are = .

- If two characters are char-equal.

- If two strings are string-equal.

- If the two cars in conses are 'equalp' and the two cdrs in conses are 'equalp'.

- If two arrays have the same number of elements and dimensions, and the corresponding elements in all dimensions are 'equalp'.

Note that only 'equalp' can compare arrays.

    (defun cl:equalp (expr-1 expr-2)
      (or (equal expr-1 expr-2)
          (and (numberp expr-1) (numberp expr-2) (= expr-1 expr-2))
          (let ((type (type-of expr-1)))
            (when (eq type (type-of expr-2))
              (case type
                (character (char-equal expr-1 expr-2))
                (string    (string-equal expr-1 expr-2))
                (cons      (do ((x (first expr-1)
                                   (if (consp expr-1) (first expr-1) expr-1))
                                (y (first expr-2)
                                   (if (consp expr-2) (first expr-2) expr-2)))
                               ((or (null expr-1)
                                    (null expr-2)
                                    (not (equalp x y)))
                                (and (null expr-1)
                                     (null expr-2)))
                             (setq expr-1 (and (consp expr-1) (rest expr-1))
                                   expr-2 (and (consp expr-2) (rest expr-2)))))
                (array     (let ((end (length expr-1)))
                             (when (eql end (length expr-2))
                               (dotimes (index end t)
                                 (and (not (equalp (aref expr-1 index)
                                                   (aref expr-2 index)))
                                      (return nil)))))))))))

cons: do is used instead of recursion because XLISP has only two kilobytes stack size. The (consp expr) tests are necessary because in a dotted list the last rest element is not a cons.

Examples:

    (cl:equalp 1 1.0)                            => T
    (cl:equalp #\a #\A)                          => T
    (cl:equalp "Abc" "aBc")                      => T
    (cl:equalp '(1 #\a "Abc") '(1.0 #\A "aBc"))  => T
    (cl:equalp #(1 #\a "Abc") #(1.0 #\A "aBc"))  => T

Nested expressions only match if the nesting matches:

    (cl:equalp '(1 (2 3)) '(1.0 (2.0 3.0))  => T
    (cl:equalp '(1 (2 3)) '((1.0 2.0) 3.0)  => NIL
    (cl:equalp '((1 2) 3) '((1.0 2.0) 3.0)  => T
    (cl:equalp '((1 2) 3) '(1.0 (2.0 3.0))  => NIL

A character does not match a string with the same character:

    (cl:equalp #\a "a")  => NIL

Back to top

Nyquist / XLISP 2.0 - Contents | Tutorials | Examples | Reference