Ύστερα από προτροπή της Αμαλίας, θα προσπαθήσω να περιγράψω, σύντομα και χωρίς ιδιαίτερη ακρίβεια, μερικά από τα βασικά στοιχεία της Scheme που έχουμε πει στο μάθημα. Σκοπός μου ΔΕΝ είναι να δώσω ένα ολοκληρωμένο manual ή tutorial, τέτοια υπάρχουν αρκετά στο Internet. Ούτε αυτά που γράφω είναι 100% σωστά, άλλωστε τώρα τη μαθαίνω και εγώ τη Scheme. Απλά, επιχειρώ να φτιάξω ένα quick and dirty σημείο αναφοράς και μερικές οδηγίες, μόνο και μόνο για να ξεκινήσουμε.
Αν και ελπίζω ότι θα λύσω κάποιες απορίες, είμαι σίγουρος ότι θα προσπεράσω άθελά μου τις περισσότερες, ενώ δεν αποκλείεται να δημιουργήσω και νέες. Γι'αυτό, κάντε τις ερωτήσεις σας στα σχόλια για να τις απαντήσω, ώστε να μπορούν όλοι να τις διαβάσουν και ΙΣΩΣ χρησιμοποιήσουμε για πρώτη φορά το blog για το σκοπό που το φτιάξαμε αρχικά (και όχι για εικόνες και βιντεάκια :P ).
Μετά το disclaimer, βαθιά ανάσα και βουτάμε στα βαθιά:
Βασικές έννοιες:
μεταβλητή: μια συμβολική αναπαράσταση που αναφέρεται σε μια ποσότητα ή μια έκφραση. Είναι ένα μέρος στη μνήμη του υπολογιστή που έχουμε δεσμεύσει για να βάζουμε δεδομένα (πχ αριθμούς ή χαρακτήρες). Η μεταβλητή είναι σαν ένα συρτάρι στο οποίο αποθηκεύουμε διάφορα αντικείμενα (τα δεδομένα).
συνάρτηση: ένα κομμάτι κώδικα (ένα σύνολο εντολών, δηλαδή) το οποίο εκτελεί μια συγκεκριμένη λειτουργία και μπορεί να είναι σχετικά ανεξάρτητο από το κυρίως πρόγραμμα. Μια συνάρτηση αποτελείται από το όνομά της, τα ορίσματα που δέχεται και το σώμα της. Όταν γράφουμε:
(define (f x) (+ x 2) )
αυτό που κάνουμε είναι ότι ορίζουμε τη συνάρτηση f, η οποία δέχεται το όρισμα x, δηλαδή το x είναι η είσοδος της συνάρτησης. Το τι θα κάνει η f όταν θα πάρει το x καθορίζεται στο σώμα της συνάρτησης. Στην προκειμένη περίπτωση, το σώμα είναι (+ x 2), δηλαδή θα προσθέσει στο x το 2. Συνήθως, το κομμάτι κώδικα αυτό, υπάρχει στο περιθώριο και εκτελείται μόνο όταν το καλέσουμε. Αυτό λέγεται κλήση συνάρτησης. Για να καλέσουμε μια συνάρτηση χρειαζόμαστε (εκτός από το όνομά της, φυσικά) να της δώσουμε όσα ορίσματα απαιτεί. Άρα, για να καλέσουμε την f με είσοδο το 5 θα δώσουμε:
(f 5)
λίστα: ένα σύνολο αντικειμένων. Κάτι σαν πολλές μεταβλητές στη σειρά που έχουν ένα όνομα.
προθεματική σύνταξη: Η εκνευριστική σύνταξη των αριθμητικών πράξεων στη Scheme, όπου πρέπει πρώτα να γράφουμε το σύμβολο της πράξης και μετά τους αριθμούς (με κενά μεταξύ τους). Για παράδειγμα, το 3+5 στη Scheme γράφεται (+ 3 5), το 4*2*8 γράφεται (* 4 2 8).
σύνταξη: το πώς πρέπει να γράφεται μια εντολή για να δουλέψει. Πχ, η define συντάσσεται:
(define μεταβλητή τιμή) ή
(define (συνάρτηση ορίσματα) (σώμα))
Μερικές βασικές εντολές:
define: η πιο ευρέως χρησιμοποιούμενη εντολή ως τώρα (να συλληφθεί ο Εβραίος!), η define μπορεί να ορίσει την τιμή μιας μεταβλητής, να ορίσει τα περιεχόμενα μιας λίστας και να ορίσει μια συνάρτηση (δηλαδή ΤΙ κάνει η συνάρτηση). Γενικά, όλα τα σφάζει, όλα τα μαχαιρώνει, χωρίς τη define δε φαίνεται να κάνουμε βήμα.
eval: η πιο ψυχανώμαλη εντολή. Σύμφωνα με το manual, αξιολογεί (evaluates) ό,τι ακολουθεί μέσα στο συγκεκριμένο πλαίσιο στο οποίο ανήκει. Με άλλα λόγια, προσπαθεί να κάνει κάτι έξυπνο. Μερικές φορές τα καταφέρνει. Έτσι, αν έχουμε ορίσει τις σχέσεις
(define George 'Athens)
(define Athens 'Greece)
και δώσουμε
(eval George)
θα απαντήσει: Greece. Σε αυτή την περίπτωση δηλαδή, θα ακολουθήσει τη σειρά των συσχετίσεων που του έχουμε δώσει.
set!: αλλάζει την τιμή μιας μεταβλητής (ή λίστας). Η διαφορά από τη define είναι ότι η set! απλά αλλάζει την τιμή, ενώ η define καταστρέφει ό,τι υπήρχε και δημιουργεί μια καινούρια μεταβλητή με το ίδιο όνομα. Η διαφορά γίνεται εμφανής με τις λίστες.
display: μια απλή εντολή! τυπώνει ό,τι ακολουθεί. Αν αυτό που ακολουθεί είναι μέσα σε διπλά εισαγωγικά (“) το τυπώνει ως είναι, αν είναι χωρίς εισαγωγικά υποθέτει ότι είναι μεταβλητή και προσπαθεί να τυπώσει την τιμή της.
car: τυπώνει το πρώτο στοιχείο μιας λίστας.
cdr: τυπώνει τη λίστα από το δεύτερο στοιχείο και μετά.
first, second, third,...: τυπώνει το πρώτο, δεύτερο, τρίτο, κλπ στοιχείο της λίστας, αντίστοιχα.
cons: προσθέτει ένα στοιχείο στην αρχή μιας λίστας.
Ένα από τα προβλήματα που παρουσιάζονται από νωρίς είναι το ότι πρέπει να συνδυάσετε πολλές συναρτήσεις. Έτσι, έχουμε ένα μακρινάρι μια συνάρτηση να καλεί μια άλλη, η οποία καλεί μια άλλη, η οποία με τη σειρά της καλεί μια άλλη, κλπ. Είναι εύκολο να χαθείτε μέσα στις πολλές παρενθέσεις και τις απανωτές εντολές. Γι' αυτό, 1) αποφύγετε να γράφετε πολλές εντολές στην ίδια γραμμή και 2) σιγουρευτείτε ότι η δομή του μακριναριού (το έχει το λεξικό! Απίστευτο!) είναι σωστή πριν γράψετε το περιεχόμενό του. Τι θέλω να πω: Αν προσπαθήσετε να γράψετε σε μία γραμμή και με τη μία το
(define (f x y) (+ (* (expt x y) x) (/ (- x y) 4)))
είναι σίγουρο ότι θα κάνετε λάθος. Αντί αυτού, προσπαθήστε να το δομήσετε βήμα-βήμα και σε πολλές σειρές, βάζοντας την παρένθεση που κλείνει ένα κομμάτι κάτω από την παρένθεση που το ανοίγει. Ας πούμε, το παραπάνω μακρινάρι σε 6 βήματα:
1.
(define (συνάρτηση)
(σώμα)
)
2.
(define (f x y)
(+ (κάτι) (κάτι άλλο) )
)
3.
(define (f x y)
(+
(κάτι)
(κάτι)
)
)
4.
(define (f x y)
(+
(* (κάτι) (κάτι) )
(/ (κάτι) (κάτι) )
)
)
5.
(define (f x y)
(+
(*
(κάτι)
(κάτι)
)
(/
(κάτι)
(κάτι)
)
)
)
6.
(define (f x y)
(+
(*
(expt x y)
x
)
(/
(- x y)
4
)
)
)
Αυτά τα ολίγα προς το παρόν. Περιμένω απορίες. Και να θυμάστε: δεν υπάρχουν ηλίθιες ερωτήσεις (μόνο ηλίθιοι άνθρωποι) :DDDDDDD
UPDATE 1/11/07:
Η Scheme δείχνει μια ασυνήθιστη προθυμία να θεωρεί σχεδόν τα πάντα ονόματα μεταβλητών ή συναρτήσεων. Αν συναντήσει μια λέξη, θα προσπαθήσει να βρει ποια μεταβλητή είναι ή κάτι αντίστοιχο. Για να την αποτρέψουμε από μία τέτοια συμπεριφορά πρέπει να βάλουμε μπροστά το quote ( ' ).
Έτσι, αν γράψουμε: (display mitsos), η Scheme θα προσπαθήσει να βρει μια μεταβλητή με όνομα mitsos και αν δεν υπάρχει, θα εμφανίσει μήνυμα λάθους. Για να εκτυπώσει το mitsos πρέπει να γράψουμε (display 'mitsos), ώστε να μετριάσουμε τις αβυσσαλέες ορέξεις της Scheme για κυνήγι ονομάτων.