Στη Clojure, οι λίστες είναι συλλογές, ακριβώς όπως οι λίστες σε άλλες γλώσσες. Όπως και άλλες γλώσσες της οικογένειας Lisp, η Clojure χρησιμοποιεί παρενθέσεις για να εκφράσει λίστες.
Οι λίστες στη Clojure μπορούν να δημιουργηθούν με έναν από δύο τρόπους. Η συνάρτηση list μπορεί να δημιουργήσει μια λίστα, ή μπορείς να χρησιμοποιήσεις το quote σε μια κυριολεκτική λίστα.
Οι λίστες είναι ξεχωριστές επειδή η Clojure τις αντιμετωπίζει ως κλήσεις. Περιμένει ότι η κλήση ξεκινά με έναν τελεστή, ο οποίος συνήθως είναι μια συνάρτηση. Τα υπόλοιπα στοιχεία της λίστας θεωρούνται τελεστέοι, που σημαίνει ότι γίνονται τα ορίσματα της συνάρτησης.
Η ειδική μεταχείριση των λιστών από τη Clojure είναι ο λόγος που δεν μπορούμε να δημιουργήσουμε απευθείας μια κυριολεκτική λίστα. Η χρήση του quote ή της συντομογραφίας του ' σε μια λίστα δηλώνει ότι η λίστα δεν πρέπει να αξιολογηθεί.
Σε αντίθεση με κάποιες σύγχρονες γλώσσες, οι λίστες στη Clojure είναι ετερογενείς, που σημαίνει ότι μπορούν να περιέχουν πολλαπλούς τύπους στοιχείων στο εσωτερικό τους, π.χ. '(2 "a" "b" 3).
Σε αντίθεση με άλλες Lisp, μια κενή λίστα στη Clojure είναι αληθής και δεν ισοδυναμεί με nil ή false.
Η Elyse ανυπομονεί πραγματικά να παίξει λίγο πόκερ (και άλλα παιχνίδια με κάρτες) στο επερχόμενο ταξίδι της στο Λας Βέγκας. Ως μεγάλη λάτρης της "αυτοπαρακολούθησης" θέλει να φτιάξει μερικές μικρές συναρτήσεις που θα τη βοηθήσουν με εργασίες παρακολούθησης και ζήτησε τη βοήθειά σου για να τις σκεφτείτε μαζί.
Η Elyse λατρεύει ιδιαίτερα το πόκερ και θέλει να παρακολουθεί πόσους γύρους παίζει, αλλά και ποιοι είναι αυτοί οι γύροι. Κάθε γύρος έχει τον δικό του αριθμό και κάθε τραπέζι δείχνει τον αριθμό του γύρου που παίζεται αυτή τη στιγμή. Η Elyse διαλέγει ένα τραπέζι και κάθεται να παίξει τον πρώτο της γύρο. Σκοπεύει να παίξει τρεις γύρους.
Υλοποίησε μια συνάρτηση rounds που παίρνει τον αριθμό του τρέχοντος γύρου και επιστρέφει μία list με αυτόν τον γύρο και τους επόμενους δύο που έρχονται:
(rounds 27)
;;=> (27 28 29)
Η Elyse έπαιξε μερικούς γύρους στο πρώτο τραπέζι, μετά έκανε διάλειμμα και έπαιξε κι άλλους γύρους σε ένα δεύτερο τραπέζι ... αλλά κατέληξε με διαφορετική λίστα για κάθε τραπέζι! Θέλει να βάλει τις δύο λίστες μαζί, ώστε να μπορεί να παρακολουθεί όλους τους γύρους πόκερ στο ίδιο σημείο.
Υλοποίησε μια συνάρτηση concat-rounds που παίρνει δύο λίστες και επιστρέφει μία list που αποτελείται από όλους τους γύρους της πρώτης list, ακολουθούμενους από όλους τους γύρους της δεύτερης list:
(concat-rounds '(27 28 29) '(35 36))
;;=> (27 28 29 35 36)
Μιλώντας για μερικούς από τους προηγούμενους γύρους πόκερ, ένας άλλος παίκτης σχολιάζει πόσο παρόμοια εξελίχθηκαν δύο από αυτούς. Η Elyse δεν είναι σίγουρη αν έπαιξε αυτούς τους γύρους ή όχι.
Υλοποίησε μια συνάρτηση contains-round? που παίρνει δύο ορίσματα, μια λίστα με τους γύρους που παίχτηκαν και έναν αριθμό γύρου.
Η συνάρτηση θα επιστρέψει true αν ο γύρος υπάρχει στη λίστα με τους γύρους που παίχτηκαν, false αν όχι:
(contains-round? '(27 28 29 35 36) 29)
;;=> true
(contains-round? '(27 28 29 35 36) 30)
;;=> false
Η Elyse θέλει να δοκιμάσει ένα νέο παιχνίδι που λέγεται Black Joe. Είναι παρόμοιο με το Black Jack, όπου ο στόχος σου είναι οι κάρτες στο χέρι σου να αθροίζουν σε μια τιμή-στόχο, αλλά στο Black Joe ο στόχος είναι ο μέσος όρος των τιμών των καρτών να είναι 7. Τον μέσο όρο μπορείς να τον βρεις αθροίζοντας όλες τις τιμές των καρτών και μετά διαιρώντας αυτό το άθροισμα με τον αριθμό των καρτών στο χέρι.
Υλοποίησε μια συνάρτηση card-average που θα επιστρέφει τη μέση τιμή ενός χεριού στο Black Joe.
(card-average '(5 6 7))
;;=> 6.0
Στο Black Joe, η ταχύτητα είναι σημαντική. Η Elyse θα προσπαθήσει να βρει έναν πιο γρήγορο τρόπο να υπολογίζει τον μέσο όρο.
Έχει σκεφτεί δύο τρόπους για να βρει έναν αριθμό σαν μέσο όρο:
Υλοποίησε τη συνάρτηση approx-average?, δεδομένης της hand, μιας λίστας που περιέχει τις τιμές των καρτών στο χέρι σου.
Επίστρεψε true αν μία or και οι δύο από τις παραπάνω στρατηγικές δίνουν έναν αριθμό ίσο με τον πραγματικό μέσο όρο.
Σημείωση: Το μήκος όλων των χεριών είναι περιττό, για να είναι πιο εύκολη η εύρεση της διαμέσου.
(approx-average? '(1 2 3))
;;=> true
(approx-average? '(2 3 4 8 8))
;;=> true
(approx-average? '(1 2 3 5 9))
;;=> false
Η Elyse, έχοντας κεντριστεί από τα αποτελέσματα του πειράματός της με τους μέσους όρους, αναρωτιέται αν ο μέσος όρος των καρτών στις ζυγές θέσεις έναντι του μέσου όρου των καρτών στις περιττές θέσεις θα έδινε τα ίδια αποτελέσματα. Ώρα για άλλη μια συνάρτηση δοκιμής!
Υλοποίησε μια συνάρτηση average-even-odd? που επιστρέφει ένα Boolean (λογική τιμή) που δείχνει αν ο μέσος όρος των καρτών στις ζυγές θέσεις είναι ίδιος με τον μέσο όρο των καρτών στις περιττές θέσεις.
(average-even-odd? '(1 2 3))
;;=> true
(average-even-odd? '(1 2 3 4))
;;=> false
Κάθε 11ο χέρι στο Black Joe είναι ένα χέρι μπόνους με κανόνα μπόνους: αν η τελευταία κάρτα που τραβάς είναι Βαλές, διπλασιάζεις την αξία της.
Υλοποίησε μια συνάρτηση maybe-double-last που παίρνει ένα χέρι και ελέγχει αν η τελευταία κάρτα είναι Βαλές (11).
Αν η τελευταία κάρτα είναι Βαλές (11), διπλασίασε την αξία της πριν επιστρέψεις το χέρι.
(maybe-double-last '(5 9 11))
;;=> '(5 9 22)
(maybe-double-last '(5 9 10))
;;=> '(5 9 10)
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Clojure με 12 έννοιες105 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.