Scheme

Η Scheme είναι η μια από τις δύο βασικές διαλέκτους της γλώσσας προγραμματισμού Lisp. Σε αντίθεση με την Common Lisp, την άλλη βασική διάλεκτο, η Scheme ακολουθεί μια μινιμαλιστική φιλοσοφία σχεδίασης, ορίζοντας ένα μικρό βασικό πυρήνα με ισχυρά εργαλεία για επέκταση της γλώσσας. Λόγω του μικρού της μεγέθους και της κομψότητάς της είναι δημοφιλής ανάμεσα στους εκπαιδευτικούς, τους σχεδιαστές γλωσσών, τους προγραμματιστές και τους ερασιτέχνες, και αυτή η ευρεία της διάδοση θεωρείται τόσο πλεονέκτημά της, όσο και μειονέκτημα, λόγω της ποικιλίας ανάμεσα στις υλοποιήσεις της.
Η Scheme αναπτύχθηκε στο MIT AI Lab του MIT από τον Guy L. Steele και τον Gerald Jay Sussman, οι οποίοι την παρουσίασαν στην ακαδημαϊκή κοινότητα μέσα από μια σειρά σημειωμάτων (memos), τα οποία σήμερα ονομάζονται "Lambda Papers", κατά την περίοδο 1975-1980. Η γλώσσα Scheme προτυποποιήθηκε σε επίσημο πρότυπο της IEEE, και σε ένα ντε φάκτο πρότυπο που ονομάζεται Αναθεωρημένηⁿ Αναφορά πάνω στην Αλγοριθμική Γλώσσα Scheme (Revisedⁿ Report on the Algorithmic Language Scheme ή RnRS). Το πρότυπο που υλοποιείται πιο συχνά είναι το R5RS (1998), και το 2007 αναγνωρίστηκε το νέο πρότυπο R6RS.
Η Scheme ήταν η πρώτη διάλεκτος της Lisp που επέλεξε τη λεκτική εμβέλεια και η πρώτη που απαίτησε από τις υλοποιήσεις της να κάνουν βελτιστοποίηση κλήσης ουράς (tail-call optimization). Ήταν επίσης μια από τις πρώτες γλώσσες προγραμματισμού που υποστήριξαν συνέχειες πρώτης κλάσης. Επηρέασε σε μεγάλο βαθμό τις προσπάθειες που οδήγησαν στην ανάπτυξη της γλώσσας Common Lisp.

Προέλευση

Η Scheme ξεκίνησε ως μια προσπάθεια να κατανοηθεί το μοντέλο Actor του Carl Hewitt, για αυτόν το λόγο οι Steele και Sussman έγραψαν έναν "μικρό διερμηνέα Lisp" χρησιμοποιώντας τη Maclisp και στη συνέχεια "πρόσθεσαν μηχανισμούς για τη δημιουργία actors και την αποστολή μηνυμάτων." Η Scheme αρχικά ονομαζόταν "Schemer", σύμφωνα με την παράδοση των άλλων γλωσσών που προήλθαν από τη Lisp, όπως η Planner και η Conniver. Το σημερινό όνομα προήλθε από τη χρήση από τους δημιουργούς της του λειτουργικού συστήματος ITS, το οποίο περιόριζε τα ονόματα αρχείων σε δύο μέρη των έξι χαρακτήρων το καθένα. Σήμερα, η λέξη "Schemer" συνήθως χρησιμοποιείται για να αναφερθεί κανείς σε έναν προγραμματιστή της Scheme.

Βασικά σχεδιαστικά χαρακτηριστικά

Σε αυτήν την υποενότητα περιγράφονται τα χαρακτηριστικά που διακρίνουν τη Scheme από άλλες γλώσσες προγραμματισμού, από τα πρώτα χρόνια που κυκλοφόρησε. Τα χαρακτηριστικά αυτά αποτελούν βασική επιρροή για κάθε προϊόν της γλώσσας, και αποτελούν κοινό γνώρισμα όλων των εκδόσεων της γλώσσας προγραμματισμόυ Scheme, από το 1973 και μετά.

Δομή ενοτήτων

Η Scheme κληρονομεί τη δομή ενοτήτων της (block structure) από προγενέστερες γλώσσες δομημένες με ενότητες και κυρίως από την ALGOL. Στη Scheme οι ενότητες υλοποιούνται από τρεις δομές δέσμευσης (binding constructs): let, let* και letrec.  Για παράδειγμα, η ακόλουθη δομή δημιουργεί μια ενότητα στην οποία ένα σύμβολο με το όνομα var δεσμεύεται στον αριθμό 10:
(define var "goose");; Κάθε αναφορά στη var εδώ δεσμεύεται στο "goose"(let ((var 10))
  ;; οι εντολές βρίσκονται εδώ. Κάθε αναφορά στη var δεσμεύεται στην τιμή 10.
  );; Κάθε αναφορά στη var εδώ δεσμεύεται στο "goose"
Οι ενότητες μπορούν να είναι εμφωλευμένες (nested) με σκοπό τη δημιουργία πολύπλοκων δομών ενοτήτων σύμφωνα με τις ανάγκες του προγραμματιστή. Η δόμηση με ενότητες για τη δημιουργία τοπικών δεσμεύσεων περιορίζει τον κίνδυνο σύγκρουσης χώρων ονομάτων (namespace collision) που μπορεί να εμφανιστεί σε άλλες περιπτώσεις.
Μια παραλλαγή της let, η let*, επιτρέπει σε δεσμεύσεις να αναφέρονται σε μεταβλητές που ορίστηκαν νωρίτερα, όπως στον εξής κώδικα:
(let* ((var1 10)
      (var2 (+ var1 12)))
  ;; Αλλά ο ορισμός της var1 δε θα μπορούσε να αναφέρεται στη var2
  )
Η άλλη παραλλαγή, η letrec, είναι σχεδιασμένη ώστε να επιτρέπει σε αμοιβαία αναδρομικές διαδικασίες να δεσμεύονται η μια στην άλλη.
;; Στηλοθέτηση των ακολουθιών αντρών-γυναικών του Hofstadter(letrec ((female (lambda(n)
                   (if (= n 0) 1
                       (- n (male (female (- n 1)))))))
         (male (lambda(n)
                 (if (= n 0) 0
                     (- n (female (male (- n 1))))))))
  (display "i male(i) female(i)")(newline)
  (do ((i 0 (+ i 1)))
      ((> i 8) #f)
    (display i) (display "   ")(display (male i))(display "         ")(display (female i))
    (newline)))
Όλες οι διαδικασίες που δεσμεύονται μέσα σε μια letrec μπορούν να αναφέρονται η μια στην άλλη με το όνομά τους, καθώς και σε τιμές μεταβλητών που ορίστηκαν νωρίτερα στην ίδια letrec, αλλά δε μπορούν να αναφέρονται σε τιμές που ορίζονται αργότερα στην ίδια letrec.
Μια παραλλαγή της let, η μορφή "ονομαστικό let", έχει ένα αναγνωριστικό μετά τη λέξη-κλειδί let. Αυτό δεσμεύει τις μεταβλητές του let στο όρισμα μιας διαδικασίας της οποίας το όνομα είναι το δοθέν αναγνωριστικό και το σώμα της είναι το σώμα της μορφής let. Το σώμα μπορεί να επαναληφθεί όσο είναι επιθυμητό με την κλήση της διαδικασίας. Το ονομαστικό let χρησιμοποιείται συχνά για την υλοποίηση της επανάληψης (iteration).
Παράδειγμα: ένας απλός μετρητής
(let loop ((n 1))
  (if (<= n 10)
    (begin
      (display n)(newline)
      (loop (+ n 1)))))
Όπως κάθε διαδικασία στη Scheme, η διαδικασία που δημιουργείται από το ονομαστικό let είναι αντικείμενο πρώτης τάξης.

Κοινός χώρος ονομάτων για διαδικασίες και μεταβλητές

Σε αντίθεση με την Common Lisp, όλα τα δεδομένα και οι διαδικασίες στη Scheme μοιράζονται έναν κοινό χώρο ονομάτων, ενώ στην Common Lisp οι συναρτήσεις και τα δεδομένα έχουν ξεχωριστούς χώρους ονομάτων, με αποτέλεσμα να είναι δυνατό μια συνάρτηση και μια μεταβλητή να έχουν το ίδιο όνομα, ενώ χρειάζεται ειδικός συμβολισμός για την αναφορά σε μια συνάρτηση ως τιμή. Αυτό είναι γνωστό και ως διαχωρισμός "Lisp-1/Lisp-2", που αναφέρεται στον ενιαίο χώρο ονομάτων της Scheme και στους ξεχωριστούς χώρους ονομάτων της Common Lisp.
Στη Scheme, οι ίδιες βασικές εντολές που χρησιμοποιούνται για το χειρισμό και τη δέσμευση δεδομένων μπορούν να χρησιμοποιηθούν για τη δέσμευση διαδικασιών. Δεν υπάρχει αντίστοιχη των εντολών defun, setf και #' της Common Lisp.
;; Μεταβλητή που δεσμεύεται σε αριθμό:(define f 10)f===> 10;; Τροποποίηση (mutation, αλλαγή της δεσμευμένης τιμής)(set! f (+ f f 6))===> 26;; Ανάθεση μιας διαδικασίας στην ίδια μεταβλητή:(set! f (lambda (n) (+ n 12)))(f 6)===> 18;; Ανάθεση του αποτελέσματος μιας έκφρασης στην ίδια μεταβλητή:(set! f (f 1))f===> 13;; συναρτησιακός προγραμματισμός:(apply + '(1 2 3 4 5 6))===> 21(set! f (lambda(n) (+ n 100)))(map f '(1 2 3))===> (101 102 103)

Πρότυπα υλοποίησης

Αυτή η υποενότητα περιγράφει σχεδιαστικές αποφάσεις που έχουν παρθεί από τη δημιουργία της γλώσσας και έχουν δώσει στη Scheme έναν ιδιαίτερο χαρακτήρα, αλλά δεν αποτελούν απευθείας αποτελέσματα του αρχικού σχεδιασμού.

Hygienic macros

Το πρότυπο R5RS εισήγαγε ένα ισχυρό σύστημα για hygienic μακροεντολές που επιτρέπει στον προγραμματιστή να προσθέσει νέες συντακτικές δομές στη γλώσσα χρησιμοποιώντας μια απλή γλώσσα ταιριάσματος προτύπων (pattern matching). (R5RS sec 4.3) Το σύστημα αυτό είχε τοποθετηθεί παλαιότερα σε ένα παράρτημα του προτύπου R4RS, ως σύστημα "υψηλού επιπέδου" μαζί με ένα "χαμηλού επιπέδου" σύστημα μακροεντολών, με τα δύο αυτά συστήματα να θεωρούνται επεκτάσεις της Scheme και όχι απαραίτητο μέρος της γλώσσας.
Οι υλοποιήσεις του συστήματος hygienic μακροεντολών, που αποκαλούνται και syntax-rules, πρέπει να συμμορφώνονται με τη λεκτική εμβέλεια της υπόλοιπης γλώσσας. Αυτό πραγματοποιείται με ειδικούς κανόνες ονομασίας και εμβέλειας για την επέκταση των μακροεντολών (macro expansion) και έτσι αποφεύγονται συχνά προγραμματιστικά λάθη που μπορούν να συμβούν σε συστήματα μακροεντολών άλλων γλωσσών προγραμματισμού. Το R6RS ορίζει ένα πιο πολύπλοκο σύστημα μετασχηματισμού, το syntax-case, που έχει υπάρξει επέκταση της γλώσσας R5RS Scheme για κάποιο χρονικό διάστημα.
;; Ορίζει μια μακροεντολή που υλοποιεί μια παραλλαγή του "if" με πολλαπλές εκφράσεις;; στον κλάδο "αληθές" και χωρίς κλάδο "ψευδές".(define-syntax when
  (syntax-rules ()
    ((when pred exp exps ...)
      (if pred (begin exp exps ...)))))
Με αυτόν τον τρόπο μπορεί να επεκταθεί εύκολα η σύνταξη της Scheme.
Οι κλήσεις των μακροεντολών και των διαδικασιών μοιάζουν πολύ-και οι δύο είναι s-εκφράσεις—αλλά ο χειρισμός τους γίνεται διαφορετικά. Όταν ο μεταγλωττιστής συναντά μια s-έκφραση στο πρόγραμμα αρχικά ελέγχει να δει αν το σύμβολο έχει οριστεί ως συντακτική λέξη-κλειδί μέσα στην τρέχουσα λεκτική εμβέλεια. Αν ναι, τότε προσπαθεί να επεκτείνει τη μακροεντολή θεωρώντας ότι τα αντικείμενα στην ουρά της s-έκφρασης είναι ορίσματα χωρίς μεταγλωττισμένο κώδικα που θα τα αποτιμήσει, και αυτό επαναλαμβάνεται αναδρομικά μέχρι να μην απομένουν άλλες κλήσεις μακροεντολών. Αν δεν είναι συντακτική λέξη-κλειδί, ο μεταγλωττιστής μεταγλωττίζει κώδικα για να αποτιμήσει τα ορίσματα στην ουρά της s-έκφρασης και για να αποτιμήσει στη συνέχεια τη μεταβλητή που αναπαρίσταται στο σύμβολο στην κεφαλή της s-έκφρασης και να την καλέσει ως διαδικασία με τις αποτιμημένες εκφράσεις της ουράς να περνιούνται ως πραγματικά ορίσματα σε αυτήν.
Οι περισσότερες υλοποιήσεις της Scheme παρέχουν επίσης επιπλέον συστήματα μακροεντολών. Κάποια από τα πιο δημοφιλή είναι τα συντακτικά κλεισίματα (syntactic closures), οι μακροεντολές ρητής μετονομασίας (explicit renaming macros) και η define-macro, ένα σύστημα μακροεντολών που δεν είναι hygienic και μοιάζει με το σύστημα defmacro της Common Lisp.

Περιβάλλοντα και η eval

Πριν από το R5RS, η Scheme δεν είχε κάποιο πρότυπο ισοδύναμο της διαδικασίας eval που υπάρχει σε άλλες διαλέκτους της Lisp, αν και το πρώτο Lambda Paper είχε περιγράψει την evaluate ως "παρόμοια με τη συνάρτηση EVAL της LISP" και η πρώτη Αναθεωρημένη Αναφορά του 1978 την αντικατέστησε με την enclose, η οποία έπαιρνε δύο ορίσματα. Η δεύτερη, τρίτη και τέταρτη αναφορά παρέλειψαν κάθε εντολή ισοδύναμη με την eval.
Ο λόγος αυτής της σύγχυσης είναι ότι στη Scheme, με τη λεκτική της εμβέλεια, το αποτέλεσμα της αποτίμησης μιας έκφρασης εξαρτάται από το πού αποτιμάται αυτή. Για παράδειγμα, δεν είναι ξεκάθαρο αν το αποτέλεσμα της αποτίμησης της ακόλουθης έκφρασης θα έπρεπε να είναι 5 ή 6:
(let ((name '+))
  (let ((+ *))
    (evaluate (list name 2 3))))
Αν αποτιμηθεί στο εξωτερικό περιβάλλον, όπου ορίζεται η name, το αποτέλεσμα είναι το άθροισμα των τελεστέων. Αν αποτιμηθεί στο εσωτερικό περιβάλλον, όπου το σύμβολο "+" έχει δεσμευτεί στην τιμή της διαδικασίας "*", το αποτέλεσμα είναι το γινόμενο των δύο τελεστέων.
Το R5RS ξεκαθαρίζει αυτήν την κατάσταση ορίζοντας τρεις διαδικασίες που επιστρέφουν περιβάλλοντα, και παρέχοντας μια διαδικασία eval που παίρνει μια s-έκφραση και ένα περιβάλλον και αποτιμά την έκφραση στο δοθέν περιβάλλον. (R5RS sec. 6.5) Το R6RS επεκτείνει αυτήν τη λειτουργικότητα παρέχοντας μια διαδικασία που ονομάζεται environment, με την οποία ο προγραμματιστής μπορεί να ορίσει ακριβώς ποια αντικείμενα θα εισαχθούν σε ένα περιβάλλον αποτίμησης.

Χειρισμός μη-αληθοτιμών σε εκφράσεις αληθείας

Στις περισσότερες διαλέκτους της Lisp, συμπεριλαμβανομένης της Common Lisp, ισχύει η σύμβαση ότι η τιμή NIL αποτιμάται στην τιμή ψευδές σε μια έκφραση αληθείας. Στη Scheme, από το πρότυπο IEEE του 1991, όλες οι τιμές εκτός της #f, συμπεριλαμβανομένης της '() που είναι η ισοδύναμη της NIL στη Scheme, αποτιμώνται στην τιμή αληθές σε μια έκφραση αληθείας. (R5RS sec. 6.3.1)
Η Scheme έχει τη σταθερά #t για την αναπαράσταση της τιμής αληθές, όπου οι περισσότερες διάλεκτοι της Lisp έχουν την T.

Ανεξαρτησία των πρωτογενών τύπων δεδομένων

Στη Scheme οι πρωτογενείς τύποι δεδομένων είναι ανεξάρτητοι. Μόνο μια από τις εξής ιδιότητες μπορεί να είναι αληθής για οποιοδήποτε αντικείμενο της Scheme: boolean?, pair?, symbol?, number?, char?, string?, vector?, port?, procedure?. (R5RS sec 3.2)
Μέσα στον αριθμητικό τύπο δεδομένων, αντίθετα, οι αριθμητικές τιμές αλληλοεπικαλύπτονται. Για παράδειγμα, μια ακέραια τιμή ικανοποιεί ταυτόχρονα όλες τις ιδιότητες integer?, rational?, real?, complex? και number?. (R5RS sec 6.2)

Είσοδος/έξοδος

Η είσοδος και η έξοδος της Scheme βασίζονται στον τύπο δεδομένων θύρα (port). (R5RS sec 6.6) Το R5RS ορίζει δυο θύρες, η πρόσβαση στις οποίες γίνεται με τις διαδικασίες current-input-port και current-output-port, οι οποίες αντιστοιχούν στις έννοιες "προκαθορισμένη έξοδος" ("standard input") και "προκαθορισμένη έξοδος" ("standard output") του Unix. Οι περισσότερες υλοποιήσεις παρέχουν επίσης μια current-error-port.  Η ανακατεύθυνση της προκαθορισμένης εισόδου και της προκαθορισμένης εξόδου υποστηρίζεται από το πρότυπο, με πρότυπες διαδικασίες όπως η with-input-from-file και η with-output-to-file. Οι πιο πολλές υλοποιήσεις παρέχουν θύρες συμβολοσειρών με παρόμοιες δυνατότητες ανακατεύθυνσης, επιτρέποντας σε πολλές κανονικές λειτουργίες εισόδου-εξόδου να εκτελούνται μέσα σε συμβολοσειρές αντί σε αρχεία, με τη χρήση διαδικασιών που ορίζονται στο SRFI 6. Το πρότυπο R6RS ορίζει πιο πολύπλοκες και ισχυρές διαδικασίες θυρών και πολλούς νέους τύπους θυρών.
Τα παρακάτω παραδείγματα είναι γραμμένα σε αυστηρή R5RS Scheme.
Παράδειγμα 1: Με την έξοδο να είναι η (current-output-port):
(let ((hello0 (lambda() (display "Hello world")(newline))))
  (hello0))
Παράδειγμα 2: Όπως το 1, αλλά χρησιμοποιεί την προαιρετική παράμετρο θύρας για τη διαδικασία εξόδου
(let ((hello1 (lambda (p) (display "Hello world" p)(newline p))))
  (hello1 (current-output-port)))
Παράδειγμα 3: Όπως το 1, αλλά η έξοδος ανακατευθύνεται σε ένα νέο αρχείο
;; NB: η with-output-to-file είναι μια προαιρετική διαδικασία στο R5RS(let ((hello0 (lambda () (display "Hello world")(newline))))
  (with-output-to-file "helloworldoutputfile" hello0))
Παράδειγμα 4: Όπως το 2, αλλά με ρητό άνοιγμα αρχείου και κλείσιμο θύρας για να αποσταλεί η έξοδος στο αρχείο
(let ((hello1 (lambda (p) (display "Hello world" p)(newline p)))
      (output-port (open-output-file "helloworldoutputfile")))
  (hello1 output-port)
  (close-output-port output-port))
Παράδειγμα 5: Όπως το 2, αλλά με τη χρήση call-with-output-file για την αποστολή της εξόδου σε ένα αρχείο.
(let ((hello1 (lambda (p) (display "Hello world" p)(newline p))))
  (call-with-output-file "helloworldoutputfile" hello1))
Για την είσοδο παρέχονται παρόμοιες διαδικασίες. Η R5RS Scheme παρέχει τις input-port? και output-port?. Για είσοδο και έξοδο χαρακτήρων, παρέχονται οι write-char, read-char, peek-char και char-ready?. Για τη γραφή και την ανάγνωση εκφράσεων της Scheme, η γλώσσα παρέχει τις read και write. Σε μια λειτουργία ανάγνωσης, το αποτέλεσμα που επιστρέφεται είναι το αντικείμενο τέλος-αρχείου (end-of-file) αν η θύρα εισόδου έχει φτάσει στο τέλος του αρχείου, και αυτό μπορεί να ελεγχθεί με τη χρήση του eof-object?.
Εκτός από το πρότυπο, το SRFI 28 ορίζει μια βασική διαδικασία μορφοποίησης που μοιάζει με τη συνάρτηση format της Common Lisp, με την οποία έχει και το ίδιο όνομα.

Ορισμός ξανά των πρότυπων διαδικασιών

Οι διαδικασίες στη Scheme δεσμεύονται σε μεταβλητές. Το πρότυπο της γλώσσας στο R5RS επίσημα δηλώνει ότι τα προγράμματα μπορούν να αλλάξουν τις δεσμεύσεις των μεταβλητών των ενσωματωμένων διαδικασιών, πρακτικά ορίζοντάς τις πάλι (R5RS, "Language changes"). Για παράδειγμα, κάποιος μπορεί να επεκτείνει τη + ώστε να δέχεται συμβολοσειρές εκτός από αριθμούς, ορίζοντάς την πάλι:
(set! +
      (let ((original+ +))
        (lambda args
          (if (and (not (null? args)) (string? (car args)))
              (apply string-append args)
              (apply original+ args)))))(+ 1 2 3)===> 6(+ "1" "2" "3")===> "123"
Στο R6RS κάθε δέσμευση, συμπεριλαμβανομένων των πρότυπων, ανήκει σε κάποια βιβλιοθήκη και όλες οι εξαγόμενες δεσμεύσεις δε μπορούν να τροποποιηθούν (immutable). (R6RS sec 7.1) Για αυτόν το λόγο, ο ορισμός ξανά των βασικών διαδικασιών μέσω τροποποίησης απαγορεύεται. Αντί για αυτό, είναι δυνατό να εισαχθεί μια διαφορετική διαδικασία με το ίδιο όνομα με μια πρότυπη, κάτι που στην πραγματικότητα δε διαφέρει πολύ από την τεχνική που περιγράφηκε παραπάνω.

Ορολογία και συμβάσεις ονοματοδοσίας

Στην Πρότυπη Scheme, οι διαδικασίες που μετατρέπουν από έναν τύπο δεδομένων σε έναν άλλο περιέχουν στο όνομά τους την ακολουθία χαρακτήρων "->", οι προτάσεις ιδιοτήτων (predicates) λήγουν σε "?", και οι διαδικασίες που αλλάζουν την τιμή δεδομένων ήδη δεσμευμένων στη μνήμη λήγουν σε "!". Αυτές οι συμβάσεις συχνά ακολουθούνται από τους προγραμματιστές της Scheme.
Σε επίσημο λόγο, όπως στα πρότυπα της Scheme, η λέξη "διαδικασία" ("procedure") χρησιμοποιείται αντί της "συνάρτησης" ("function") για να αναφέρεται σε μια λ-έκφραση ή σε μια πρωτογενή διαδικασία. Στον κανονικό λόγο οι λέξεις "διαδικασία" και "συνάρτηση" χρησιμοποιούνται εξίσου. Η εφαρμογή διαδικασίας μερικές φορές ονομάζεται επίσημα συνδυασμός (combination).
Όπως και σε άλλες διαλέκτους της Lisp, ο όρος "thunk" χρησιμοποιείται στη Scheme για να αναφέρεται σε μια διαδικασία χωρίς ορίσματα. Ο όρος "σωστή αναδρομή ουράς" ("proper tail recursion") αναφέρεται στην ιδιότητα που έχουν όλες οι υλοποιήσεις της Scheme, της εφαρμογής βελτιστοποίησης κλήσης ουράς ("tail-call optimization") ώστε να υποστηρίζουν άπειρο αριθμό ενεργών κλήσεων ουράς.
Η μορφή των τίτλων των εγγράφων των προτύπων από το R3RS, "Revisedⁿ Report on the Algorithmic Language Scheme", είναι αναφορά στον τίτλο του εγγράφου του προτύπου της ALGOL 60, "Revised Report on the Algorithmic Language Algol 60," και η σελίδα με την περίληψη (Summary) του R3RS μοιάζει με αυτήν της Αναφοράς της ALGOL 60.

Πρότυπες μορφές και διαδικασίες

Η γλώσσα ορίζεται στα πρότυπα R5RS (1998) και R6RS (2007). Αυτά ορίζουν πρότυπες "μορφές" ("forms"): λέξεις-κλειδιά με την αντίστοιχη σύνταξη, που παρέχουν τη δομή ελέγχου της γλώσσας, και πρότυπες διαδικασίες που εκτελούν συνηθισμένες εργασίες.

Αιτήματα για Υλοποίηση στη Scheme - μεταφέρσιμες επεκτάσεις του προτύπου

Λόγω του μινιμαλισμού της Scheme, πολλές κοινές διαδικασίες και συντακτικές μορφές δεν ορίζονται από το πρότυπο. Για να κρατηθεί η βασική γλώσσα μικρή αλλά να είναι εύκολη η προτυποποίηση επεκτάσεων, η κοινότητα της Scheme ακολουθεί μια διαδικασία "Αιτήματος Υλοποίησης στη Scheme" ("Scheme Request for Implementation", SRFI), με την οποία ορίζονται βιβλιοθήκες επέκτασης μέσω προσεκτικής συζήτησης προτάσεων επέκτασης, κάτι που βελτιώνει τη μεταφερσιμότητα του κώδικα. Πολλά από τα SRFI υποστηρίζονται από όλες ή από τις περισσότερες υλοποιήσεις της Scheme.
Μια πλήρης λίστα από SRFI που έχουν γίνει αποδεκτά σε τελικό στάδιο είναι διαθέσιμη στο http://srfi.schemers.org/final-srfis.html.

Υλοποιήσεις

Η κομψή και μινιμαλιστική σχεδίαση έχουν κάνει τη Scheme δημοφιλή στόχο για σχεδιαστές γλωσσών, ερασιτέχνες και εκπαιδευτικούς, και λόγω του μικρού μεγέθους του μέσου διερμηνέα της είναι επίσης δημοφιλής για ενσωματωμένα συστήματα και ως γλώσσα σεναρίων. Αυτό έχει ως αποτέλεσμα πολλές υλοποιήσεις,. Οι πιο πολλές διαφέρουν μεταξύ τους τόσο που η μεταφορά προγραμμάτων από τη μια στην άλλη είναι αρκετά δύσκολη και το μικρό μέγεθος της βασικής γλώσσας σημαίνει ότι είναι εξαιρετικά δύσκολο να γραφεί ένα χρήσιμο αλλά πολύπλοκο πρόγραμμα σε πρότυπη και μεταφέρσιμη Scheme. Το πρότυπο R6RS ορίζει μια αρκετά πιο ευρεία γλώσσα ώστε να είναι πιο ελκυστικό στον προγραμματιστή.
Σχεδόν όλες οι υλοποιήσεις παρέχουν έναν κλασικό βρόχο διάβασε-αποτίμησε-τύπωσε (read-eval-print loop) στο στυλ της Lisp για τη δημιουργία προγραμμάτων και την αποσφαλμάτωση. Πολλές επίσης μεταγλωττίζουν τα προγράμματα σε Scheme σε εκτελέσιμα δυαδικά αρχεία. Είναι επίσης συνήθης η ενσωμάτωση κώδικα Scheme σε προγράμματα γραμμένα σε άλλες γλώσσες, καθώς η σχετική απλότητα των υλοποιήσεων της Scheme κάνει τη γλώσσα να είναι δημοφιλής για την προσθήκη δυνατοτήτων σεναρίων σε μεγαλύτερα συστήματα που έχουν αναπτυχθεί σε γλώσσες όπως η C. Η Gambit, η Chicken και η Bigloo δουλεύουν μεταγλωττίζοντας της Scheme σε C, διευκολύνοντας έτσι την ενσωμάτωση. Επιπλέον, ο μεταγλωττιστής της Bigloo μπορεί να ρυθμιστεί ώστε να παράγει κώδικα byte για την Εικονική Μηχανή της Java (JVM), ενώ έχει και μια πειραματική γεννήτρια κώδικα byte για το .Net.
Κάποιες υλοποιήσεις υποστηρίζουν επιπλέον χαρακτηριστικά. Για παράδειγμα, η Kawa και η JScheme παρέχουν ενοποίηση με τις κλάσεις της Java, και οι μεταγλωττιστές από Scheme σε C συνήθως διευκολύνουν τη χρήση εξωτερικών βιβλιοθηκών γραμμένων σε C, μέχρι και την ενσωμάτωση κανονικού κώδικα C στον πηγαίο κώδικα Scheme. Ένα άλλο παράδειγμα είναι το PVTS που προσθέτει ένα σύνολο από οπτικά εργαλεία για την υποστήριξη της εκμάθησης της Scheme.

R6RS

Μια νέα διαδικασία προτυποποίησης της γλώσσας άρχισε το 2003 στο Scheme workshop, με σκοπό να δημιουργήσει ένα πρότυπο R6RS το 2006. Η διαδικασία αυτή διέφερε από τις προηγούμενες όσον αφορά τη συμφωνία μεταξύ των συμμετεχόντων.
Το R6RS έχει ένα πρότυπο σύστημα μονάδων κώδικα (modules), που επιτρέπει τη διάκριση μεταξύ της βασικής γλώσσας και των βιβλιοθηκών. Δημοσιεύτηκαν κάποιες προσωρινές εκδόσεις του προτύπου R6RS, με την τελευταία έκδοση αυτών να είναι η R5.97RS. Μετά από ψηφοφορία, το νέο πρότυπο δημοσιεύτηκε στις 28 Αυγούστου 2007.
Οι νεότερες εκδόσεις διάφορων υλοποιήσεων της Scheme, π.χ. η Ikarus, η Larceny, η Racket και η Ypsilon υποστηρίζουν το πρότυπο R6RS. Υπάρχει μια μεταφέρσιμη υλοποίηση αναφοράς των προτεινόμενων βιβλιοθηκών που πρόκειται να αλλάξουν για το R6RS, που ονομάζεται psyntax, η οποία μπορεί να φορτώνει και να εκκινεί τον εαυτό της σωστά με πολλές παλαιότερες υλοποιήσεις της Scheme.
Το R6RS εισάγει αρκετές σημαντικές αλλαγές στη γλώσσα. Ο πηγαίος κώδικας ορίζεται πια σε Unicode, και ένα μεγαλύτερο υποσύνολο των χαρακτήρων Unicode μπορεί να εμφανιστεί σε σύμβολα της Scheme και σε αναγνωριστικά, ενώ υπάρχουν και άλλες μικρές αλλαγές στους λεκτικούς κανόνες. Τα δεδομένα χαρακτήρων επίσης ορίζονται σε Unicode. Πολλές πρότυπες διαδικασίες έχουν μετακινηθεί στις νέες πρότυπες διαδικασίες, οι οποίες με τη σειρά τους αποτελούν μια μεγάλη επέκταση του προτύπου, περιέχοντας διαδικασίες και συντακτικές μορφές που παλαιότερα δεν ήταν μέρος του προτύπου. Για την υποστήριξη των βιβλιοθηκών και τη δημιουργία περισσότερων βιβλιοθηκών, εισάγεται ένα νέο σύστημα μονάδων κώδικα ενώ το πρότυπο περιγράφει και συστήματα για το χειρισμό εξαιρέσεων. Το syntax-rules έχει αντικατασταθεί από ένα ισχυρότερο εργαλείο συντακτικής αφαίρεσης (syntax-case), το οποίο επιτρέπει τη χρήση ολόκληρης της Scheme κατά το χρόνο επέκτασης των μακροεντολών. Οι υλοποιήσεις που συμφωνούν με το πρότυπο πρέπει να υποστηρίζουν τον πλήρη αριθμητικό πύργο της Scheme, και η σημασιολογία των αριθμών έχει επεκταθεί, κυρίως για την υποστήριξη του προτύπου IEEE 754 για την αναπαράσταση αριθμών κινητής υποδιαστολής.
Το νέο πρότυπο έχει προκαλέσει κάποιες αντιδράσεις γιατί εμφανίζεται να απομακρύνεται από τη μινιμαλιστική φιλοσοφία των προηγούμενων. Τον Αύγουστο του 2009, η αρμόδια επιτροπή της Scheme (Scheme Steering Committee) που επιβλέπει τη διαδικασία της προτυποποίησης ανακοίνωσε την πρόθεσή της να συστήσει το διαχωρισμό της γλώσσας σε δύο γλώσσες: μια μεγάλη και σύγχρονη γλώσσα προγραμματισμού για προγραμματιστές, και ένα υποσύνολο της μεγάλης αυτής έκδοσης που να διατηρεί το μινιμαλισμό που επιθυμούν οι εκπαιδευτικοί και όσοι υλοποιούν απλά τη γλώσσα.

Χρήση

Η Scheme χρησιμοποιείται από αρκετά εκπαιδευτικά ιδρύματα και πολλά μαθήματα εισαγωγής στην επιστήμη των υπολογιστών χρησιμοποιούν τη Scheme μαζί με το βιβλίο Structure and Interpretation of Computer Programs (SICP). Τα τελευταία 12 χρόνια, η PLT λειτουγεί το εγχείρημα TeachScheme!, το οποίο έχει φέρει σε επαφή περίπου 600 καθηγητές της δευτεροβάθμιας εκπαίδευσης και χιλιάδες μαθητές με τις βασικές αρχές του προγραμματισμού Scheme. Το παλιό μάθημα εισαγωγής στον προγραμματισμού στο MIT (6.001) χρησιμοποιούσε τη Scheme στη διδασκαλία του. Αν και το 6.001 έχει αντικατασταθεί από πιο σύγχρονα μαθήματα, το SICP εξακολουθεί να διδάσκεται στο MIT.
Το βιβλίο How to Design Programs του Matthias Felleisen χρησιμοποιείται από κάποια ιδρύματα ανώτατης εκπαίδευσης για τα μαθήματα εισαγωγής στον προγραμματισμό.
Ο LambdaBeans είναι διορθωτής κειμένου Scheme ανοιχτού κώδικα, με χρωματισμό σύνταξης, συμπλήρωση κώδικα και άλλα χαρακτηριστικά των διορθωτών του είδους.
Υπάρχουν σχετικά λίγα παραδείγματα πραγματικής χρήσης της Scheme για μη-εκπαιδευτικούς σκοπούς. Η Document Style Semantics and Specification Language (DSSSL), που ορίζει φύλα στυλ της SGML, χρησιμοποιεί ένα υποσύνολο της Scheme. Επιπλέον, το γνωστό πρόγραμμα επεξεργασίας εικόνας ανοιχτού κώδικα GIMP χρησιμοποιεί τη Scheme ως γλώσσα σεναρίων. Η Guile έχει υιοθετηθεί από το εγχείρημα GNU ως η επίσημη γλώσσα σεναρίων και η υλοποίηση αυτή της Scheme έχει ενσωματωθεί σε εφαρμογές όπως το GNU LilyPond και GnuCash, λειτουργώντας ως γλώσσα σεναρίων για επεκτάσεις. Παρομοίως η Guile ήταν η γλώσσα σεναρίων του γραφικού περιβάλλοντος GNOME, και το GNOME ακόμα έχει ένα εγχείρημα που παρέχει συνδέσεις από Guile στις βιβλιοθήκες του. Η Elk Scheme χρησιμοποιείται από τη Synopsys ως γλώσσα σεναρίων για τα εργαλεία TCAD της. Ο Shiro Kawai, προγραμματιστής της ταινίας Final Fantasy: The Spirits Within, χρησιμοποίησε τη Scheme ως γλώσσα σεναρίων για τον έλεγχο της μηχανής φωτοαπόδοσης πραγματικού χρόνου. Το App Inventor του Google για το Android χρησιμοποιεί τη Scheme, ενώ η Kawa χρησιμοποιείται για τη μεταγλώττιση κώδικα Scheme σε κώδικα byte για την Εικονική Μηχανή της Java που εκτελείται στις συσκευές Android.