Ισ

Ισότητα σε Common Lisp

1 άσκηση

Σχετικά με την έννοια Ισότητα

Η 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
  • τα cons είναι equal αν τα στοιχεία τους είναι equal. Αυτό γίνεται αναδρομικά.
  • οι συμβολοσειρές και τα διανύσματα bit είναι equal αν τα στοιχεία τους είναι eql
  • οι πίνακες άλλων τύπων συγκρίνονται σαν να χρησιμοποιείται eq
  • τα pathnames είναι equal αν είναι λειτουργικά ισοδύναμα. (Εδώ υπάρχει περιθώριο για συμπεριφορά που εξαρτάται από την υλοποίηση, όσον αφορά τη διάκριση πεζών-κεφαλαίων στις συμβολοσειρές που αποτελούν τα συστατικά μέρη των pathnames.)
  • τα αντικείμενα οποιουδήποτε άλλου τύπου συγκρίνονται σαν να χρησιμοποιείται 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 αν έχουν την ίδια τιμή, ακόμα κι αν δεν είναι του ίδιου τύπου
  • οι χαρακτήρες και οι συμβολοσειρές συγκρίνονται χωρίς διάκριση πεζών-κεφαλαίων
  • τα cons είναι equalp αν τα στοιχεία τους είναι equalp. Αυτό γίνεται αναδρομικά.
  • οι πίνακες είναι equalp αν έχουν τον ίδιο αριθμό διαστάσεων, οι διαστάσεις αυτές είναι οι ίδιες και κάθε στοιχείο είναι equalp.
  • οι δομές είναι equalp αν έχουν την ίδια κλάση και τις ίδιες υποδοχές και καθεμία από αυτές τις υποδοχές είναι equalp μεταξύ των δύο δομών.
  • οι πίνακες κατακερματισμού είναι equalp αν έχουν και οι δύο την ίδια συνάρτηση :test, έχουν τα ίδια κλειδιά (συγκρινόμενα με αυτή τη συνάρτηση :test) και αυτά τα κλειδιά έχουν τις ίδιες τιμές, όπως συγκρίνονται με 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. Αυτές οι συναρτήσεις θα παρουσιαστούν και θα συζητηθούν στις σχετικές έννοιες.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα

Μάθε την έννοια Ισότητα