Common Lisp में समानता जाँचने के लिए कई अलग-अलग प्रेडिकेट हैं।
यह दूसरी प्रोग्रामिंग भाषाओं से अलग है, जिनमें शायद एक या दो ही होते हैं (जैसे == और ===)।
Common Lisp में इनमें से कुछ प्रेडिकेट किसी खास टाइप के लिए होते हैं, जबकि बाकी सामान्य होते हैं।
यहाँ बात इन्हीं सामान्य प्रेडिकेट की होगी।
सामान्य समानता के चार प्रेडिकेट हैं, और ये इस बात में एक-दूसरे से अलग हैं कि किसे वे "बराबर" मानते हैं, यह तय करने में कितने सख्त हैं।
ये सबसे सख्त से सबसे ढीले के क्रम में हैं: eq, eql, equal और equalp।
इनकी परिभाषाएँ थोड़े में (कुछ बारीकियाँ छोड़कर) इस तरह हैं:
eq: समानता का मतलब है कि दोनों ऑब्जेक्ट बिल्कुल एक ही हैं।
उदाहरण के लिए:
(eq 'a 'a) ; => T
(eq (list 1 2) (list 1 2)) ; => NIL
eql: समानता का मतलब है: दो संख्याएँ जिनका टाइप और वैल्यू एक ही हो, या दो अक्षर जो एक ही हों, और बाकी किसी भी चीज़ के लिए यह कि वे eq हों।
उदाहरण के लिए:
(eql 1 1) ; => T
(eql #\a #\a) ; => T
(eql 1 1.0) ; => NIL
(eql #\a #\A) ; => NIL
equal: समानता का मतलब है: दो लिस्ट equal होती हैं अगर उनका हर एलिमेंट भी equal हो; दो स्ट्रिंग equal होती हैं अगर उनका हर एलिमेंट eql हो; दो ऐरे equal होते हैं अगर वे eq हों; बाकी सब कुछ equal होता है अगर वे eql हों।
उदाहरण के लिए:
(equal (list 1 2) (list 1 2)) ; => T
(equal #(1 2) #(1 2)) ; => NIL
(equal "foo" "foo") ; => T
equalp: समानता का मतलब है: स्ट्रिंग और अक्षरों की तुलना छोटे-बड़े अक्षरों का फर्क किए बिना की जाती है; संख्याओं की तुलना में कुछ टाइप बदलाव होता है; लिस्ट और ऐरे equalp होते हैं अगर उनका हर एलिमेंट भी equalp हो, स्ट्रक्चर तब जब उनका टाइप एक ही हो और सारे स्लॉट equalp हों, और हैश टेबल तब जब उनकी की और वैल्यू equalp हों
उदाहरण के लिए:
(equalp "foo" "FoO") ; => T
(equalp 3 3.0) ; => T
(equalp (make-a-structure :slot1 1 :slot2 2)
(make-a-structure :slot1 1 :slot2 2)) ; => T
लेस्ली नाम के Lisp Alien अपने भूलभुलैया वाले रोबोट को प्रोग्राम कर रहे हैं (जैसा कि नए-नए Lisp Alien अक्सर करते हैं) और उन्हें थोड़ी मदद चाहिए। भूलभुलैया कई कमरों से बनी है। हर कमरे में कई दरवाज़े हैं। हर दरवाज़े के लिए एक चाबी चाहिए। अगर आप किसी दरवाज़े पर गलत चाबी लगाते हैं तो वह दरवाज़ा फट सकता है (रोबोट के बारे में चिंता की ज़रूरत नहीं, उसे कोई नुकसान नहीं होगा, लेकिन जले के निशान रगड़कर मिटाना लेस्ली के लिए काफी झंझट भरा काम है)। अगर रोबोट के पास कोई भी दरवाज़ा खोलने वाली चाबी न हुई, तो पूरा कमरा फट जाएगा! (फिर कहें, चिंता की बात नहीं, इससे कोई नुकसान नहीं होगा, बस साफ करना झंझट भरा होगा।)
लेस्ली की मदद के लिए आपको रोबोट को हर कमरे की सही चाबी देनी है। रोबोट कमरे के हर दरवाज़े पर यह चाबी एक-एक करके लगाएगा और जो पहला दरवाज़ा खुलेगा, उसी में से निकल जाएगा।
हर टेस्ट एक भूलभुलैया है और हर जाँच एक कमरा। आपको ऐसे प्रेडिकेट फंक्शन लिखने हैं जिनका परिणाम तब T होता है जब आर्गुमेंट बराबर हों, और NIL तब जब वे बराबर न हों।
इस भूलभुलैया में सिर्फ एक ही कमरा है। आपको एक ऐसा फंक्शन देना है जो बता सके कि दो ऑब्जेक्ट एक ही ऑब्जेक्ट हैं या नहीं।
उदाहरण के लिए:
a ; => "pizza"
b ; => "pizza"
(key-object-identity a a) ; => T
(key-object-identity a b) ; => NIL
क्योंकि a और b दिखने में एक जैसे हैं, पर वे एक ही ऑब्जेक्ट नहीं हैं।
इस भूलभुलैया में दो कमरे हैं। पहले कमरे का दरवाज़ा तभी खुलेगा जब आपकी चाबी बता सके कि दो संख्याएँ बिल्कुल बराबर हैं या नहीं। दूसरे कमरे के लिए ऐसी चाबी चाहिए जो संख्याओं की बराबरी जाँचते समय थोड़ी छूट देती हो।
उदाहरण के लिए:
a ; => 13
b ; => 13.0
c ; => 13
(key-numbers a b) ; => NIL
(key-numbers a c) ; => T
(key-numbers-of-different-types a b) ; => T
क्योंकि a और b संख्या के रूप में एक ही हैं, पर उनके टाइप अलग-अलग हैं।
इस भूलभुलैया में दो कमरे हैं। पहले कमरे का दरवाज़ा तभी खुलेगा जब आपकी चाबी बता सके कि दो अक्षर बिल्कुल बराबर हैं या नहीं। दूसरे कमरे के लिए ऐसी चाबी चाहिए जो अक्षरों की तुलना करते समय छोटे-बड़े अक्षरों का फर्क न करे।
उदाहरण के लिए:
a ; => #\X
b ; => #\x
c ; => #\X
(key-characters a b) ; => NIL
(key-characters a c) ; => T
(key-characters-case-insensitively a b) ; => T
क्योंकि दो अक्षरों की तुलना करते समय छोटे-बड़े अक्षरों का फर्क सिर्फ बहुत छूट देने वाले प्रेडिकेट ही अनदेखा करते हैं।
अक्षरों की भूलभुलैया की तरह यहाँ भी पहले कमरे के लिए ऐसी चाबी चाहिए जो जाँचे कि दो स्ट्रिंग बराबर हैं या नहीं, और दूसरे कमरे के लिए ऐसी चाबी जो छोटे-बड़े अक्षरों का फर्क न करते हुए तुलना करे।
उदाहरण के लिए:
a ; => "pizza"
b ; => "PIZZA"
c ; => "pizza"
(key-strings a b) ; => NIL
(key-strings a c) ; => T
(key-strings-case-insensitively a b) ; => T
क्योंकि दो स्ट्रिंग की तुलना करते समय छोटे-बड़े अक्षरों का फर्क सिर्फ बहुत छूट देने वाले प्रेडिकेट ही अनदेखा करते हैं।
यह एक बड़ी भूलभुलैया है जिसमें कई कमरे हैं। हर कमरे के लिए ऐसी चाबी चाहिए जो जाँचे कि कॉन्स के अंदर मौजूद चीज़ें बराबर हैं या नहीं। हर कमरा अलग-अलग अंदरूनी चीज़ों वाले कॉन्स की बराबरी जाँचेगा: सिंबल, संख्या और अक्षर; और कुछ कमरों के लिए इन चीज़ों की और भी लचीली बराबरी की परिभाषाएँ चाहिए होंगी।
उदाहरण के लिए:
syms-a ; => (left . right)
syms-b ; => (up . down)
syms-c ; => (left . right)
chars-a ; => (#\x . #\y)
chars-b ; => (#\x . #\Y)
chars-c ; => (#\x . #\y)
nums-a ; => (13 . 23)
nums-b ; => (13 . 23.0)
nums-c ; => (13 . 23)
(key-conses-of-symbols syms-a syms-b) ; => NIL
(key-conses-of-symbols syms-a syms-c) ; => T
(key-conses-of-characters chars-a chars-b) ; => NIL
(key-conses-of-characters chars-a chars-c) ; => T
(key-conses-of-characters-case-insensitively
chars-a chars-b) ; => T
(key-conses-of-numbers nums-a nums-b) ; => NIL
(key-conses-of-numbers nums-a nums-c) ; => T
(key-conses-of-numbers-of-different-types
nums-a nums-b) ; => T
क्योंकि कॉन्स के अंदर देखने वाला बराबरी का प्रेडिकेट भी तुलना करते समय छोटे-बड़े अक्षरों या संख्या के टाइप को अनदेखा करने के लिए काफी छूट देने वाला नहीं हो सकता।
यह भूलभुलैया ज़्यादा आसान है और इसमें सिर्फ दो कमरे हैं। पहले कमरे के लिए ऐसी चाबी चाहिए जो जाँचे कि ऐरे वही ऐरे हैं या नहीं। दूसरे कमरे के लिए ऐसी चाबी चाहिए जो ऐरे के अंदर की चीज़ें जाँचे।
उदाहरण के लिए:
a ; => #[13 23]
b ; => #[13 23]
c ; => #[13 23.0]
(key-arrays a b) ; => NIL
(key-arrays a c) ; => NIL
(key-arrays-loosely a b) ; => T
(key-arrays-loosely a c) ; => T
क्योंकि ऐरे के अंदर की चीज़ें बराबर हैं या नहीं, यह सिर्फ बहुत छूट देने वाले बराबरी जाँचने वाले ही जाँचते हैं।
Exercism पर साइन अप कीजिए और Common Lisp को 27 कॉन्सेप्ट92 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।