Common Lisp هم مانند زبانهای دیگر مجموعهای از قواعد دارد که بر اساس آنها تصمیم گرفته میشود آیا دو شیء «یکسان» هستند یا نه. این قواعد چهار سطح را تعریف میکنند و هر سطح تابعی دارد که همان سطح از بررسی را انجام میدهد. سطحها از سختگیرانهترین به آزادترین مرتب شدهاند.
eqسطح اول، اینهمانی شیء است.
این برابری با تابع eq بررسی میشود.
دو شیئی که برای برابری بررسی میشوند باید دقیقاً همان یک شیء باشند:
(eq 'apples 'apples) ; => T
(eq 'apples 'oranges) ; => NIL
(eq '(a b c) '(a b c) ; => NIL (these two lists have the same contents but are not the same list)
(let ((list1 '(a b c)) (list2 list1))
(eq list1 list2)) ; => T (these two lists are the same list)
eqlسطح دوم برابری اعداد و کاراکترها را هم اضافه میکند.
این برابری با تابع eql بررسی میشود.
شیوهی انجام بررسی به نوع آرگومانها بستگی دارد:
eq باشند، eql هم هستندeql هستندeql هستند.(eql 1 1) ; => T
(eql 1 1/1) ; => NIL (one number is an integer, the other a rational)
(eql #\c #\c) ; => T
(eql #\c #\C) ; => NIL (case is different)
شاید بپرسید چرا اعداد و کاراکترها با eq برای اینهمانی شیء مقایسه نمیشوند.
استاندارد Common Lisp به پیادهسازیها اجازه میدهد اگر بخواهند اعداد و کاراکترها را کپی کنند.
بنابراین 0 و 0 ممکن است eq نباشند، چون میتوانند نمونههای متفاوتی از عدد 0 باشند.
equalسطح سوم شباهت ساختاری را بررسی میکند.
این برابری با equal بررسی میشود.
شیوهی انجام بررسی به نوع آرگومانها بستگی دارد:
eq مقایسه میشوندeql مقایسه میشوندequal باشند equal هستند.
این کار بهصورت بازگشتی انجام میشود.eql باشند equal هستندeq مقایسه میشوندequal هستند.
(اینجا جا برای رفتار وابسته به پیادهسازی وجود دارد، در مورد حساسیت به بزرگی و کوچکی حروف در رشتههایی که اجزای نام مسیر را میسازند.)eq مقایسه میشوند(equal '(a (b c)) '(a (b c))) ; => T (conses are equal if their contents are equal)
(equal "hello" "hello") ; => T
(equal "hello" "HELLO") ; => NIL
(equal #(1 2 3) #(1 2 3)) ; => NIL (arrays are equal only if eq)
(equal #P"foo/bar.md" #P"foo/bar.md") ; => T (pathnames are equal if "functionally equivalent"
equalpسطح چهارم و آزادترین سطح برابری با equalp بررسی میشود.
شیوهی انجام بررسی به نوعها بستگی دارد:
equalp باشند، آنگاه equalp هستندequalp هستند، حتی اگر از یک نوع نباشندequalp باشند equalp هستند.
این کار بهصورت بازگشتی انجام میشود.equalp باشد، equalp هستند.equalp باشد، equalp هستند.:test یکسان داشته باشند، کلیدهای یکسان داشته باشند (وقتی با همان تابع :test مقایسه شوند) و آن کلیدها مقادیر یکسانی داشته باشند (وقتی با equalp مقایسه شوند)، equalp هستند.(equalp 1 1.0) ; => T
(equalp #\c #\C) ; => T
(equalp "hello" "HELLO") ; => T
(equalp #(1 2 3) #(1.0 2.0 3.0)) ; => T (arrays contain elements which are `equalp`)
(equal #S(TEST :SLOT1 'a :SLOT2 'b)
#S(TEST :SLOT1 'a :SLOT2 'b)) ; => T (structures of the same class with slots that have values which are `equalp`)
موارد بالا توابع برابری «عمومی» هستند.
آنها همانطور که تعریف شدهاند برای هر نوعی کار میکنند.
این میتواند زمانی مفید باشد که کد عمومی مینویسید و تا زمان اجرا نمیدانید چه نوع اشیائی را مقایسه خواهید کرد.
اما وقتی نوع چیزهایی که مقایسه میشوند را میدانید، عموماً «سبک بهتر» این است که از توابع برابری مختص نوع استفاده کنید.
برای نمونه string= بهجای equal.
این توابع در مفاهیم مرتبط معرفی و بررسی میشوند.