Two expressions are 'equalp':
If the expressions
If two numbers of arbitrary type
If two characters are
If two strings are
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.
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