Στην Common Lisp μπορείς να γράψεις "σχόλια" που ο υπολογιστής αγνοεί.
Τα σχόλια μονής γραμμής αρχίζουν με μία ή περισσότερες άνω τελείες (;) και, περιστασιακά, μπορεί να δεις το εξής:
(code...) ; => value
Όπου το σχόλιο χρησιμοποιείται για να δείξει ποια τιμή επιστρέφει η Common Lisp αφού εκτελέσει τον κώδικα σε αυτή τη γραμμή.
Είναι ιδιωματικό να χρησιμοποιείς μία μόνο άνω τελεία για ένα σύντομο σχόλιο στο τέλος μιας γραμμής, δύο για ένα μεγαλύτερο σχόλιο πάνω από ένα τμήμα κώδικα, τρεις για ένα μεγάλο σχόλιο που περιγράφει κάτι όπως μια συνάρτηση και τέσσερις για ένα σχόλιο όπως μια κεφαλίδα στην αρχή ενός αρχείου πηγαίου κώδικα.
Όλα τα αντικείμενα της Common Lisp είναι είτε "άτομα" (απλές, αδιαίρετες τιμές) είτε "conses" (κατασκευασμένα από τη συνάρτηση κατασκευής "cons").
Ένα cons αποτελείται από δύο μέρη: το πρώτο στοιχείο και τα υπόλοιπα στοιχεία.
Για ιστορικούς λόγους, αυτά τα δύο μέρη ονομάζονται car και cdr.
Όταν αυτά τα cons αξιολογούνται ως κώδικας, το πρώτο στοιχείο (car) αντιπροσωπεύει τη συνάρτηση που καλείται, ενώ τα υπόλοιπα στοιχεία
(cdr) αντιπροσωπεύουν τα ορίσματα αυτής της συνάρτησης:
(<function> <arg1> <arg2> ... <argN>)
; ^ car ^ | ^ cdr ^
Όλος ο κώδικας της Common Lisp αποτελείται από S-Expressions (Symbolic Expressions). Για συντομία ονομάζονται sexprs. Κάθε sexpr είναι είτε ένα άτομο είτε ένα cons. Όταν οι S-Expressions αξιολογούνται, επιστρέφουν αυτόματα κάποια τιμή που παίρνει τη θέση της έκφρασης. Όταν γράφεις τις δικές σου συναρτήσεις (χρησιμοποιώντας defun), η τελευταία τιμή μέσα στο σώμα της defun επιστρέφεται αυτόματα:
;; Defining a new function
(defun gimme-foo () 'foo)
;; Calling the function as an S-Expression
(gimme-foo) ; => FOO
Τα σύμβολα στη Common Lisp είναι ειδικές τιμές που μπορούν να δείχνουν σε άλλες τιμές ή, στην περίπτωση των λέξεων-κλειδιών, στον εαυτό τους. Όταν τα σύμβολα αξιολογούνται από τη Lisp, αντικαθίστανται με τις τιμές στις οποίες δείχνουν:
foo ; => <whatever-foo-points-to>
:foo ; => :FOO
Σημείωσε ότι οι λέξεις-κλειδιά συμβολίζονται με μία άνω και κάτω τελεία στην αρχή (:).
Η παράθεση, δηλαδή η προσθήκη του ' πριν από μια S-expression, λέει στη Lisp να μην αξιολογήσει αυτή την έκφραση.
Παραθέτοντας το 'foo στο παράδειγμά μας με defun, αποφύγαμε η Lisp να προσπαθήσει να αναζητήσει (και να αποτύχει να βρει) αυτό στο οποίο υποτίθεται ότι έδειχνε το FOO, και αντ' αυτού να επιστρέψει την ίδια την τιμή FOO.
Αν το FOO δεν έχει οριστεί πουθενά στο πρόγραμμά μας:
foo ; => <ERROR! Lisp doesn't know what foo points to!>
'foo ; => FOO
Για την ώρα, μπορείς να το θεωρήσεις απλώς έναν τρόπο για να επιστρέφεις σύμβολα από μια συνάρτηση, αλλά θα ξαναδούμε την παράθεση και θα εξερευνήσουμε περαιτέρω τις επιπτώσεις της σε μελλοντικές ασκήσεις εννοιών.
Εσύ! Ναι, εσύ, γενναίε λίσπερ! Ο Lenny, ο εξωγήινος της Lisp, χρειάζεται τη βοήθειά σου! Ο Lenny θέλει να πάει να χαλαρώσει με όλους τους άλλους εξωγήινους της Lisp, αλλά οι γονείς του τού είπαν ότι δεν πάει πουθενά μέχρι να συγυρίσει το δωμάτιό του.
Το πρόβλημα είναι ότι ο Lenny μετά βίας βλέπει το πάτωμα! Δεν ξεχωρίζει τα άτομα από τα cons, τα σύμβολα από τις λέξεις-κλειδιά, τα car από τα cdr!
Μπορείς να βοηθήσεις τον Lenny να τακτοποιήσει αυτό το χάος; Μην ξεχάσεις τις παρενθέσεις σου, θα τις χρειαστείς!
Πριν ξεκινήσει ο Lenny, χρειάζεται μια υπενθύμιση για το πώς μοιάζουν τα σύμβολα και οι λέξεις-κλειδιά, έχει περάσει καιρός από την τελευταία φορά που τακτοποίησε το δωμάτιό του... Βοήθησε τον Lenny ορίζοντας δύο συναρτήσεις: τη lennys-favorite-food, που αξιολογείται σε κάποιο σύμβολο, και τη lennys-secret-keyword, που αξιολογείται σε κάποια λέξη-κλειδί. Για παράδειγμα:
(lennys-favorite-food) ; => LASAGNA
(lennys-secret-keyword) ; => :ALIENS-ARE-REAL
Σημείωσε ότι μπορείς να επιστρέψεις όποιο σύμβολο ή λέξη-κλειδί θέλεις (αν δεν σου αρέσει η λαζάνια ή δεν πιστεύεις στους εξωγήινους).
Μόλις ο Lenny θυμηθεί τα σύμβολα και τις λέξεις-κλειδιά, είναι ώρα για τακτοποίηση! Για να ξεδιαλύνει όλες τις S-εκφράσεις που είναι σκορπισμένες στο δωμάτιό του, ο Lenny χρειάζεται βοήθεια για να καταλάβει τι είναι cons και τι άτομο. Μπορείς να βοηθήσεις υλοποιώντας δύο συναρτήσεις, τη is-an-atom-p και τη is-a-cons-p:
(is-an-atom-p 'one-thing) ; => T
(is-an-atom-p '(two things)) ; => NIL
(is-a-cons-p 'one-thing) ; => NIL
(is-a-cons-p '(two things)) ; => T
Σε αυτή την ενότητα, υπάρχουν αρκετές ενσωματωμένες συναρτήσεις της Lisp που μπορεί να σου φανούν χρήσιμες. Επιπλέον, για την ώρα, μπορείς απλώς να θεωρήσεις το T ως αληθές και το NIL ως ψευδές.
Τέλος, τα cons του Lenny είναι πολύ ογκώδη για να τακτοποιηθούν προσεγμένα στη θέση τους, οπότε πρέπει να τα χωρίσει σε μικρότερα κομμάτια. Μπορείς να βοηθήσεις ορίζοντας δύο ακόμη συναρτήσεις που θα τα σπάσουν σε μικρότερα μέρη (τη first-thing και τη rest-of-it);
(first-thing '(first second third)) ; => FIRST
(rest-of-it '(first second third)) ; => (SECOND THIRD)
Και πάλι, κάποιες από τις ενσωματωμένες συναρτήσεις της Common Lisp μπορεί να σου φανούν χρήσιμες εδώ.
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Common Lisp με 27 έννοιες92 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.