Scheme

Από τη Βικιπαίδεια, την ελεύθερη εγκυκλοπαίδεια
Μετάβαση σε: πλοήγηση, αναζήτηση

Η Scheme είναι η μια από τις δύο βασικές διαλέκτους της γλώσσας προγραμματισμού Lisp. Σε αντίθεση με την Common Lisp, την άλλη βασική διάλεκτο, η Scheme ακολουθεί μια μινιμαλιστική φιλοσοφία σχεδίασης, ορίζοντας ένα μικρό βασικό πυρήνα με ισχυρά εργαλεία για επέκταση της γλώσσας. Λόγω του μικρού της μεγέθους και της κομψότητάς της είναι δημοφιλής ανάμεσα στους εκπαιδευτικούς, τους σχεδιαστές γλωσσών, τους προγραμματιστές και τους ερασιτέχνες, και αυτή η ευρεία της διάδοση θεωρείται τόσο πλεονέκτημά της, όσο και μειονέκτημα, λόγω της ποικιλίας ανάμεσα στις υλοποιήσεις της.[1]

Η Scheme αναπτύχθηκε στο MIT AI Lab του MIT από τον Guy L. Steele και τον Gerald Jay Sussman, οι οποίοι την παρουσίασαν στην ακαδημαϊκή κοινότητα μέσα από μια σειρά σημειωμάτων (memos), τα οποία σήμερα ονομάζονται "Lambda Papers", κατά την περίοδο 1975-1980. Η γλώσσα Scheme προτυποποιήθηκε σε επίσημο πρότυπο της IEEE,[2] και σε ένα ντε φάκτο πρότυπο που ονομάζεται Αναθεωρημένηn Αναφορά πάνω στην Αλγοριθμική Γλώσσα Scheme (Revisedn Report on the Algorithmic Language Scheme ή RnRS). Το πρότυπο που υλοποιείται πιο συχνά είναι το R5RS (1998),[3] και το 2007 αναγνωρίστηκε το νέο πρότυπο R6RS.[4][5]

Η Scheme ήταν η πρώτη διάλεκτος της Lisp που επέλεξε τη λεκτική εμβέλεια και η πρώτη που απαίτησε από τις υλοποιήσεις της να κάνουν βελτιστοποίηση κλήσης ουράς (tail-call optimization). Ήταν επίσης μια από τις πρώτες γλώσσες προγραμματισμού που υποστήριξαν συνέχειες πρώτης κλάσης. Επηρέασε σε μεγάλο βαθμό τις προσπάθειες που οδήγησαν στην ανάπτυξη της γλώσσας Common Lisp.[6]

Πίνακας περιεχομένων

Προέλευση[Επεξεργασία | επεξεργασία κώδικα]

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

Σημαντικά χαρακτηριστικά[Επεξεργασία | επεξεργασία κώδικα]

Δείτε επίσης: Lisp

Η Scheme είναι κυρίως συναρτησιακή γλώσσα προγραμματισμού και μοιράζεται πολλά χαρακτηριστικά με άλλα μέλη της οικογένειας γλωσσών προγραμματισμού της Lisp. Η απλή σύνταξη της Scheme βασίζεται σε s-εκφράσεις, οι οποίες είναι λίστες με παρενθέσεις που αποτελούνται από έναν τελεστή στην αρχή τους ακολουθούμενο από τα ορίσματά του. Κατά αυτόν τον τρόπο, τα προγράμματα σε Scheme αποτελούνται από ακολουθίες από εμφωλευμένες λίστες. Οι λίστες είναι επίσης η βασική δομή δεδομένων στη Scheme, κάτι που οδηγεί σε μια στενή σχέση ισοδυναμίας μεταξύ του κώδικα και των δεδομένων (homoiconicity). Τα προγράμματα σε Scheme μπορούν εύκολα να δημιουργήσουν και να αποτιμήσουν κομμάτια κώδικα Scheme δυναμικά.

Η χρήση της λίστας ως βασικής δομής δεδομένων είναι ένα χαρακτηριστικό που μοιράζονται όλες οι διάλεκτοι της Lisp. Η Scheme κληρονομεί ένα πλούσιο σύνολο από πρωτογενείς συναρτήσεις επεξεργασίας λιστών όπως οι cons, car και cdr, καθώς και συναρτήσεις πρώτης τάξης από τη Lisp. Η Scheme χρησιμοποιεί αυστηρά (strictly) μεταβλητές δυναμικού τύπου και υποστηρίζει συναρτήσεις πρώτης τάξης: οι συναρτήσεις μπορούν να αποδοθούν σε μεταβλητές ως τιμές ή να δοθούν ως ορίσματα σε συναρτήσεις.

Η ενότητα αυτή ασχολείται κυρίως με πρωτότυπα χαρακτηριστικά της γλώσσας, συμπεριλαμβανομένων αυτών που την ξεχωρίζουν από άλλες διαλέκτους της Lisp. Εκτός και αν αναφέρεται διαφορετικά, οι περιγραφές των χαρακτηριστικών αναφέρονται στο πρότυπο R5RS.

Στα παραδείγματα, ο συμβολισμός "===> αποτέλεσμα" χρησιμοποιείται για να δείξει το αποτέλεσμα της αποτίμησης μιας έκφρασης που βρίσκεται στην αμέσως προηγούμενη γραμμή. Ο ίδιος συμβολισμός χρησιμοποιείται και στο R5RS.

Βασικά σχεδιαστικά χαρακτηριστικά[Επεξεργασία | επεξεργασία κώδικα]

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

Μινιμαλισμός[Επεξεργασία | επεξεργασία κώδικα]

Η Scheme είναι μια πολύ απλή γλώσσα και είναι πολύ πιο εύκολο να υλοποιηθεί από άλλες γλώσσες παρόμοιας εκφραστικής ισχύος.[8] Αυτή η ευκολία οφείλεται στη χρήση του λ-λογισμού ως πρωτογενούς φόρμας από την οποία προκύπτει το μεγαλύτερο μέρος της σύνταξης της γλώσσας. Για παράδειγμα, από τις 23 δομές που βασίζονται σε s-εκφράσεις που περιγράφονται στο πρότυπο R5RS Scheme, οι 11 κατηγοριοποιούνται ως παραγόμενες ή μορφές βιβλιοθήκης, οι οποίες μπορούν να γραφούν ως μακροεντολές (macros) που περιέχουν βασικότερες (κυρίως) λ-μορφές.[9][3]

Βασικές μορφές: define, lambda, if, quote, unquote, unquote-splicing, quasiquote, define-syntax, let-syntax, letrec-syntax, syntax-rules, set!
Μορφές βιβλιοθήκης: do, let, let*, letrec, cond, case, and, or, begin, named let, delay

Παράδειγμα: μια μακροεντολή που υλοποιεί τη let ως έκφραση, χρησιμοποιώντας τη lambda για να εκτελεί τις δεσμεύσεις μεταλβητών (variable bindings).

(define-syntax let
  (syntax-rules ()
    ((let ((var expr) ...) body ...)
      ((lambda (var ...) body ...) expr ...))))

Κατά αυτόν τον τρόπο, χρησιμοποιώντας τη let όπως ορίστηκε παραπάνω σε μια υλοποίηση Scheme θα έγραφε ξανά τον κώδικα "(let ((a 1)(b 2)) (+ b a))" σαν "((lambda (a b) (+ b a)) 1 2)", που μειώνει τις εργασίες της υλοποίησης, χρησιμοποιώντας στιγμιότυπα της κάθε διαδικασίας.

Το 1998 ο Sussman και ο Steele τόνισαν ότι ο μινιμαλισμός της Scheme δεν ήταν σχεδιαστικός στόχος που τον επιδίωξαν συνειδητά, αλλά προέκυψε από τη διαδικασία σχεδίασης.[7]

Λεκτική εμβέλεια[Επεξεργασία | επεξεργασία κώδικα]

Όπως οι περισσότερες σύγχρονες γλώσσες προγραμματισμού, και σε αντίθεση με τη Emacs Lisp και με προηγούμενες διαλέκτους της Lisp όπως η Maclisp, η Scheme έχει λεκτική εμβέλεια: όλες οι δυνατές δεσμεύσεις μεταβλητών σε μια μονάδα προγράμματος μπορούν να αναλυθούν διαβάζοντας το κείμενο της μονάδας αυτής χωρίς να πρέπει να ληφθούν υπόψη οι συνθήκες υπό τις οποίες μπορεί να κληθεί.

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

Η έρευνα του Sussman πάνω στην ALGOL τον ενέπνευσε να ενσωματώσει στη νέα έκδοση του της Lisp, στις αρχές της δεκαετίας του 1970, ένα ασυνήθιστο μοντέλο εμβέλειας. Θέση του ήταν ότι οι μηχανισμοί λεκτικής εμβέλειας όπως αυτοί της ALGOL, θα βοηθούσαν στον αρχικό τους στόχο της υλοποίησης του μοντέλου Actor στη Lisp.[7]

Οι βασικές ιδέες για το πώς ενσωματώνεται η λεκτική εμβέλεια σε μια διάλεκτο της Lisp έγιναν γνωστές από το Sussman και το Steele στο Lambda Paper του 1975 με τον τίτλο "Scheme: An Interpreter for Extended Lambda Calculus",[10] στο οποίο υιοθέτησαν την έννοια του λεκτικού κλείσιμου, το οποίο είχε περιγραφεί σε ένα "AI Memo" το 1970 από τον Joel Moses, ο οποίος με τη σειρά του, υποστήριξε ότι η ιδέα προέρχεται από τον Peter J. Landin.[11]

λ-λογισμός[Επεξεργασία | επεξεργασία κώδικα]

Κύριο λήμμα: λ-λογισμός

Ο μαθηματικός συμβολισμός του Alonzo Church που ονομάζεται λ-λογισμός, επηρέασε τη Lisp όσον αφορά τη χρήση της λέξης-κλειδί "lambda" για την εισαγωγή μιας διαδικασίας (procedure), ενώ σε αυτόν οφείλεται και η ανάπτυξη πολλών τεχνικών συναρτησιακού προγραμματισμού, όπως η χρήση συναρτήσεων υψηλής τάξης στη Lisp. Οι πρώιμες διάλεκτοι της Lisp δεν ήταν κατάλληλες για να εκφράσουν το λ-λογισμό λόγω του τρόπου με τον οποίο χειρίζονταν τις ελεύθερες μεταβλητές.[7]

Η εισαγωγή της λεκτικής εμβέλειας έλυσε το πρόβλημα, εξισώνοντας κάποιες μορφές του λ-συμβολισμού και του πώς αυτός εκφράζεται πρακτικά σε μια πραγματική γλώσσα προγραμματισμού. οι Sussman και Steele έδειξαν ότι η νέα γλώσσα μπορούσε να χρησιμοποιηθεί για να προκύψουν με κομψό τρόπο η προστακτική και η δηλωτική σημασιολογία όλων των άλλων γλωσσών προγραμματισμού, όπως της ALGOL ή της Fortran, και η δυναμική εμβέλεια των άλλων διαλέκτων της Lisp, με τη χρήση λ-εκφράσεων, όχι ως απλά στιγμιότυπα διαδικασιών αλλά ως δομές ελέγχου και τελεστές τροποποίησης του περιβάλλοντος.[12] Εισήγαγαν το στυλ περάσματος συνεχειών μαζί με την πρώτη περιγραφή της Scheme στο πρώτο από τα Lambda Papers, και σε επόμενες δημοσιεύσεις έδειξαν το πόσο ισχυρή είναι αυτή χρήση στην πράξη του λ-λογισμού.

Δομή ενοτήτων[Επεξεργασία | επεξεργασία κώδικα]

Η 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 είναι αντικείμενο πρώτης τάξης.

Αναδρομή ουράς[Επεξεργασία | επεξεργασία κώδικα]

Κύριο λήμμα: Αναδρομή ουράς

Η Scheme έχει μια δομή επανάληψης, τη do, αλλά στη Scheme συνηθίζεται να χρησιμοποιείται η αναδρομή ουράς για την έκφραση της επανάληψης. Οι υλοποιήσεις της Scheme που συμφωνούν με το πρότυπο απαιτείται να βελτιστοποιούν τις κλήσεις ουράς (tail calls), ώστε να μπορούν να υποστηρίξουν άπειρες ενεργές κλήσεις ουράς (R5RS sec. 3.5)[3]—μια ιδιότητα που το πρότυπο περιγράφει σαν σωστή αναδρομή ουράς (proper tail recursion)— με αποτέλεσμα ο προγραμματιστής να μπορεί να γράφει επαναληπτικούς αλγορίθμους με τη χρήση αναδρομής, κάτι που είναι ευκολότερο. Οι διαδικασίες που έχουν αναδρομή ουράς και η μορφή ονομαστικό let υποστηρίζουν την επανάληψη μέσω αναδρομής ουράς.

;; Στηλοθέτηση των τετραγώνων από το 0 έως το 9:
;; Το loop είναι απλά ένα σύμβολο που χρησιμοποιήθηκε σαν ετικέτα.
;; Οποιοδήποτε άλλο σύμβολο είναι επίσης κατάλληλο.
(let loop ((i 0))
  (if (not (= i 10))
     (begin
        (display i)(display " squared = ")(display (* i i))(newline)
        (loop (+ i 1)))))

Συνέχειες πρώτης τάξης[Επεξεργασία | επεξεργασία κώδικα]

Οι συνέχειες στη Scheme είναι αντικείμενα πρώτης τάξης. Η Scheme παρέχει τη διαδικασία call-with-current-continuation (γνωστή και σαν call/cc) για να δεσμεύσει την τρέχουσα συνέχεια, πακετάροντάς τη σαν διαδικασία διαφυγής (escape procedure) που δεσμεύεται σε μια παράμετρο μιας διαδικασίας που όρισε ο προγραμματιστής. (R5RS sec. 6.4)[3] Οι συνέχειες πρώτης τάξης επιτρέπουν στον προγραμματιστή να δημιουργεί μη-τοπικές δομές ελέγχου όπως οι επαναλήπτες (iterators), οι συρρουτίνες (coroutines), και η οπισθοδρόμηση (backtracking).

Στο επόμενο παράδειγμα, που είναι ένα κλασικό προγραμματιστικό πρόβλημα, φαίνεται πώς χειρίζεται η Scheme τις συνέχειες ως αντικείμενα πρώτης τάξης, δεσμεύοντάς τις σε μεταβλητές και περνώντας τις ως παραμέτρους σε διαδικασίες.

(let* ((yin
         ((lambda (cc) (display "@") cc) (call-with-current-continuation (lambda (c) c))))
       (yang
         ((lambda (cc) (display "*") cc) (call-with-current-continuation (lambda (c) c)))) )
    (yin yang))

Όταν εκτελεστεί, ο κώδικας εμφανίζει την εξής ακολουθία από μετρητές: "@*@**@***@****@*****@******@*******@********..."

Η έννοια της συνέχειας πρώτης τάξης επεκτάθηκε στο πρότυπο R5RS. Ένας περιορισμός της call/cc είναι ότι παράγει συνέχειες που μπορούν να χειριστούν μόνο μια παράμετρο. Το R5RS αναίρεσε αυτόν τον περιορισμό, ορίζοντας δύο νέες διαδικασίες: η values ορίζεται σαν τη διαδικασία που δίνει όλες της τις παραμέτρους στη συνέχειά της, και η call-with-values παράγει μια συνέχεια που απλά περνάει τα ορίσματά της σε μια διαδικασία. (R5RS sec. 6.4)[3]

Αποτέλεσμα των παραπάνω είναι να μπορούν να γραφούν διαδικασίες που επιστρέφουν παραπάνω από μια τιμές. Ένα απλό παράδειγμα της χρησιμότητας αυτής της ισχυρής δομής είναι:

;; Μια διαδικασία που επιστρέφει το όνομα χρήστη και τον κωδικό
(define (credentials) (values "myuser" "mypassword"))
 
;; Μια διαδικασία που εκτελεί ταυτοποίηση ενός ονόματος χρήστη και ενός κωδικού
(define (login username password)
  ;; κώδικας ταυτοποίησης και εισόδου του χρήστη στο σύστημα
   )
 
;; Στέλνει τα δεδομένα στη διαδικασία ταυτοποίησης.
(call-with-values credentials login)

Με τη χρήση της σύνταξης receive που εμφανίστηκε στο SRFI 8,[13] η παραπάνω call-with-values μπορεί να γραφεί ως εξής:

(receive (username password) (credentials) (login username password))

Η μορφή receive είναι ένα παράδειγμα δομής ενότητας όπως η μορφή let, και μπορεί να οδηγήσει σε καθαρότερο κώδικα.

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

Σε αντίθεση με την Common Lisp, όλα τα δεδομένα και οι διαδικασίες στη Scheme μοιράζονται έναν κοινό χώρο ονομάτων, ενώ στην Common Lisp οι συναρτήσεις και τα δεδομένα έχουν ξεχωριστούς χώρους ονομάτων, με αποτέλεσμα να είναι δυνατό μια συνάρτηση και μια μεταβλητή να έχουν το ίδιο όνομα, ενώ χρειάζεται ειδικός συμβολισμός για την αναφορά σε μια συνάρτηση ως τιμή. Αυτό είναι γνωστό και ως διαχωρισμός "Lisp-1/Lisp-2", που αναφέρεται στον ενιαίο χώρο ονομάτων της Scheme και στους ξεχωριστούς χώρους ονομάτων της Common Lisp.[14]

Στη 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 έναν ιδιαίτερο χαρακτήρα, αλλά δεν αποτελούν απευθείας αποτελέσματα του αρχικού σχεδιασμού.

Αριθμητικός πύργος[Επεξεργασία | επεξεργασία κώδικα]

Η Scheme ορίζει ένα σχετικά πλήρες σύνολο από αριθμητικούς τύπους δεδομένων, όπως οι τύποι των μιγαδικών και των ρητών αριθμών, το οποίο είναι γνωστό στη Scheme σαν "ο αριθμητικός πύργος" ("numerical tower"). (R5RS sec. 6.2[3]) Το πρότυπο θεωρεί τους τύπους αφηρημένους και δεν υποχρεώνει αυτόν που υλοποιεί τη γλώσσα σε κάποια συγκεκριμένη εσωτερική αναπαράσταση.

Οι αριθμοί μπορεί να έχουν την ιδιότητα της ακρίβειας. Ένας ακριβής αριθμός μπορεί να παραχθεί μόνο από μια ακολουθία λειτουργιών ακρίβειας πάνω σε ακριβείς αριθμούς - δηλαδή η μη-ακρίβεια είναι "μεταδοτική". Το πρότυπο ορίζει ότι οποιεσδήποτε δύο υλοποιήσεις πρέπει να παράγουν ισοδύναμα αποτελέσματα για όλες τις λειτουργίες που έχουν ως αποτέλεσμα ακριβείς αριθμούς.

Το πρότυπο R5RS ορίζει τις διαδικασίες exact->inexact και inexact->exact που μπορούν να χρησιμοποιηθούν για να αλλάξουν την ακρίβεια ενός αριθμού. Το πρότυπο R6RS τις παραλείπει από το βασικό κείμενο αλλά τις ορίζει ως διαδικασίες συμβατότητας με το R5RS στη βασική βιβλιοθήκη (rnrs r5rs (6)).

Σύμφωνα με το πρότυπο R5RS, οι υλοποιήσεις της Scheme δε χρειάζεται να υλοποιήσουν ολόκληρο τον αριθμητικό πύργο αλλά πρέπει να υλοποιήσουν "ένα σωστό υποσύνολο που να συμφωνεί τόσο με τους σκοπούς της υλοποίησης όσο και με το πνεύμα της γλώσσας Scheme." (R5RS sec. 6.2.3).[3] Το νέο πρότυπο R6RS απαιτεί την υλοποίηση ολόκληρου του αριθμητικού πύργου και "τα αντικείμενα ακεραίων ακρίβειας και τα αντικείμενα ρητών αριθμών ακρίβειας πρακτικά άπειρου μεγέθους και ακρίβειας, και να υλοποιηθούν συγκεκριμένες διαδικασίες...που να επιστρέφουν πάντα ακριβή αποτελέσματα όταν τους δίνονται ακριβείς παράμετροι" (R6RS sec. 3.4, sec. 11.7.1).[4]

Παράδειγμα 1: αριθμητική ακρίβειας σε μια υλοποίηση που υποστηρίζει ρητούς μιγαδικούς αριθμούς ακρίβειας.

;; Άθροισμα τριών ρητών αριθμών και δύο ρητών μιγαδικών αριθμών
(define x (+ 1/3 1/4 -1/5 -1/3i 405/50+2/3i))
x
===> 509/60+1/3i
;; Έλεγχος ακρίβειας.
(exact? x)
===> #t

Παράδειγμα 2: Η ίδια αριθμητική σε μια υλοποίηση που δεν υποστηρίζει ρητούς αριθμούς ακρίβειας, ούτε μιγαδικούς αριθμούς, αλλά δέχεται πραγματικούς αριθμούς σε συμβολισμό ρητών.

;; Άθροισμα τεσσάρων ρητών πραγματικών αριθμών
(define xr (+ 1/3 1/4 -1/5 405/50))
;; Άθροισμα δύο ρητών πραγματικών αριθμών
(define xi (+ -1/3 2/3))
xr
===> 8.48333333333333
xi
===> 0.333333333333333
;; Έλεγχος ακρίβειας
(exact? xr)
===> #f
(exact? xi)
===> #f

Και οι δύο υλοποιήσεις συμφωνούν με το πρότυπο R5RS αλλά η δεύτερη δε συμφωνεί με το R6RS γιατί δεν υλοποιεί τον πλήρη αριθμητικό πύργο.

Καθυστερημένη αποτίμηση[Επεξεργασία | επεξεργασία κώδικα]

Δείτε επίσης: Οκνηρή αποτίμηση

Η Scheme υποστηρίζει την καθυστερημένη αποτίμηση (delayed evaluation) μέσω της μορφής delay και της διαδικασίας force.

(define a 10)
(define eval-aplus2 (delay (+ a 2)))
(set! a 20)
(force eval-aplus2)
===> 22
(define eval-aplus50 (delay (+ a 50)))
(let ((a 8))
  (force eval-aplus50))
===> 70
(set! a 100)
(force eval-aplus2)
===> 22

Το λεκτικό περιβάλλον του αρχικού ορισμού της υπόσχεσης (promise) διατηρείται, και η τιμή του επίσης διατηρείται μετά από την πρώτη χρήση της force. Η υπόσχεση αποτιμάται μόνο μια φορά.

Αυτές οι πρωτογενείς εντολές, που παράγουν ή χειρίζονται τιμές γνωστές ως υποσχέσεις (promises), μπορούν να χρησιμοποιηθούν για να υλοποιηθούν προχωρημένες δομές οκνηρής αποτίμησης, όπως οι ροές (streams).[15]

Στο πρότυπο R6RS, δεν είναι πια πρωτογενείς εντολές αλλά παρέχονται ως μέρος της βιβλιοθήκης συμβατότητας R5RS (rnrs r5rs (6)).

Στο R5RS, δίνεται μια προτεινόμενη υλοποίηση της delay και της force, που υλοποιεί την υπόσχεση ως διαδικασία χωρίς ορίσματα (ένα thunk) και χρησιμοποιεί την τεχνική της απομνημόνευσης (memoization) για να είναι βέβεαιο ότι θα αποτιμηθεί μια μόνο φορά, ανεξάρτητα από τον αριθμό των φορών που θα κληθεί η force. (R5RS sec. 6.4)[3]

Το SRFI 41 επιτρέπει την έκφραση πεπερασμένων και άπειρων ακολουθιών με σημαντική οικονομία. Για παράδειγμα, ακολουθεί ένας ορισμός της ακολουθίας Φιμπονάτσι χρησιμοποιώντας τις συναρτήσεις που ορίζονται στο SRFI 41:[15]

;; Ορίζει την ακολουθία Φιμπονάτσι:
(define fibs
  (stream-cons 0
    (stream-cons 1
      (stream-map +
        fibs
        (stream-cdr fibs)))))
;; Υπολογίζει τον εκατοστό αριθμό της ακολουθίας:
(stream-ref fibs 99)
===>  218922995834555169026

Σειρά αποτίμησης των παραμέτρων μιας διαδικασίας[Επεξεργασία | επεξεργασία κώδικα]

Οι περισσότερες διάλεκτοι της Lisp ορίζουν μια σειρά αποτίμησης για τις παραμέτρους μιας διαδικασίας, όχι όμως η Scheme. Η σειρά αποτίμησης-συμπεριλαμβανομένης της σειράς με την οποία αποτιμάται η έκφραση στη θέση του τελεστή-μπορεί να επιλεγεί από την υλοποίηση ανάλογα με την κάθε κλήση και ο μόνος περιορισμός είναι ότι "το αποτέλεσμα κάθε ταυτόχρονης αποτίμησης του τελεστή και των εκφράσεων-τελεστέων πρέπει να συμφωνεί με κάποια ακολουθιακή σειρά αποτίμησης." (R5RS sec. 4.1.3)[3]

(let ((ev (lambda(n) (display "Evaluating ")
                     (display (if (procedure? n) "procedure" n))
                     (newline) n)))
  ((ev +) (ev 1) (ev 2)))
===> 3

Η ev είναι μια διαδικασία που περιγράφει το όρισμα που της περνιέται, και στη συνέχεια επιστρέφει την τιμή του ορίσματος αυτού. Σε αντίθεση με άλλες διαλέκτους της Lisp, η εμφάνιση μιας έκφρασης στη θέση τελεστή (το πρώτο αντικείμενο) μιας έκφρασης της Scheme είναι σωστή, αρκεί το αποτέλεσμα της έκφρασης αυτής να είναι διαδικασία.

Καλώντας τη διαδικασία "+" για την πρόσθεση 1 και 2, οι εκφράσεις (ev +), (ev 1) και (ev 2) μπορούν να αποτιμηθούν με οποιαδήποτε σειρά, αρκεί το αποτέλεσμά τους να μην είναι αυτό που θα προέκυπτε αν αποτιμούνταν παράλληλα, Επομένως, οι ακόλουθες τρεις γραμμές μπορούν να εμφανιστούν με οποιαδήποτε σειρά στην πρότυπη Scheme όταν εκτελεστεί ο παραπάνω κώδικας, αν και το κείμενο μιας γραμμής δεν παρεμβάλλεται με κάποιας άλλης, αφού αυτό θα παραβίαζε τον περιορισμό της ακολουθιακής αποτίμησης.

Evaluating 1
Evaluating 2
Evaluating procedure

Hygienic macros[Επεξεργασία | επεξεργασία κώδικα]

Το πρότυπο R5RS εισήγαγε ένα ισχυρό σύστημα για hygienic μακροεντολές που επιτρέπει στον προγραμματιστή να προσθέσει νέες συντακτικές δομές στη γλώσσα χρησιμοποιώντας μια απλή γλώσσα ταιριάσματος προτύπων (pattern matching). (R5RS sec 4.3)[3] Το σύστημα αυτό είχε τοποθετηθεί παλαιότερα σε ένα παράρτημα του προτύπου R4RS, ως σύστημα "υψηλού επιπέδου" μαζί με ένα "χαμηλού επιπέδου" σύστημα μακροεντολών, με τα δύο αυτά συστήματα να θεωρούνται επεκτάσεις της Scheme και όχι απαραίτητο μέρος της γλώσσας.[16]

Οι υλοποιήσεις του συστήματος 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"[10] και η πρώτη Αναθεωρημένη Αναφορά του 1978 την αντικατέστησε με την enclose, η οποία έπαιρνε δύο ορίσματα. Η δεύτερη, τρίτη και τέταρτη αναφορά παρέλειψαν κάθε εντολή ισοδύναμη με την eval.

Ο λόγος αυτής της σύγχυσης είναι ότι στη Scheme, με τη λεκτική της εμβέλεια, το αποτέλεσμα της αποτίμησης μιας έκφρασης εξαρτάται από το πού αποτιμάται αυτή. Για παράδειγμα, δεν είναι ξεκάθαρο αν το αποτέλεσμα της αποτίμησης της ακόλουθης έκφρασης θα έπρεπε να είναι 5 ή 6:[17]

(let ((name '+))
  (let ((+ *))
    (evaluate (list name 2 3))))

Αν αποτιμηθεί στο εξωτερικό περιβάλλον, όπου ορίζεται η name, το αποτέλεσμα είναι το άθροισμα των τελεστέων. Αν αποτιμηθεί στο εσωτερικό περιβάλλον, όπου το σύμβολο "+" έχει δεσμευτεί στην τιμή της διαδικασίας "*", το αποτέλεσμα είναι το γινόμενο των δύο τελεστέων.

Το R5RS ξεκαθαρίζει αυτήν την κατάσταση ορίζοντας τρεις διαδικασίες που επιστρέφουν περιβάλλοντα, και παρέχοντας μια διαδικασία eval που παίρνει μια s-έκφραση και ένα περιβάλλον και αποτιμά την έκφραση στο δοθέν περιβάλλον. (R5RS sec. 6.5)[3] Το R6RS επεκτείνει αυτήν τη λειτουργικότητα παρέχοντας μια διαδικασία που ονομάζεται environment, με την οποία ο προγραμματιστής μπορεί να ορίσει ακριβώς ποια αντικείμενα θα εισαχθούν σε ένα περιβάλλον αποτίμησης.

Χειρισμός μη-αληθοτιμών σε εκφράσεις αληθείας[Επεξεργασία | επεξεργασία κώδικα]

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

Η Scheme έχει τη σταθερά #t για την αναπαράσταση της τιμής αληθές, όπου οι περισσότερες διάλεκτοι της Lisp έχουν την T.

Ανεξαρτησία των πρωτογενών τύπων δεδομένων[Επεξεργασία | επεξεργασία κώδικα]

Στη Scheme οι πρωτογενείς τύποι δεδομένων είναι ανεξάρτητοι. Μόνο μια από τις εξής ιδιότητες μπορεί να είναι αληθής για οποιοδήποτε αντικείμενο της Scheme: boolean?, pair?, symbol?, number?, char?, string?, vector?, port?, procedure?. (R5RS sec 3.2)[3]

Μέσα στον αριθμητικό τύπο δεδομένων, αντίθετα, οι αριθμητικές τιμές αλληλοεπικαλύπτονται. Για παράδειγμα, μια ακέραια τιμή ικανοποιεί ταυτόχρονα όλες τις ιδιότητες integer?, rational?, real?, complex? και number?. (R5RS sec 6.2)[3]

Προτάσεις ισοδυναμίας[Επεξεργασία | επεξεργασία κώδικα]

Η Scheme έχει τρεις διαφορετικούς τύπους ισοδυναμίας μεταξύ τυχαίων αντικειμένων, με τρεις διαφορετικές προτάσεις ισοδυναμίας (equivalence predicates), που είναι σχεσιακοί τελεστές που ελέγχουν την ισότητα και είναι ο eq?, ο eqv? και ο equal?:

  • ο eq? αποτιμάται σε #f εκτός και αν οι παράμετροί του αναπαριστούν το ίδιο αντικείμενο δεδομένων στη μνήμη,
  • ο eqv? είναι γενικά παρόμοιος με τον eq? αλλά χειρίζεται τα πρωτογενή αντικείμενα (π.χ. χαρακτήρες και αριθμούς) με ειδικό τρόπο με αποτέλεσμα η eqv? να είναι αληθής για αριθμούς που αναπαριστούν την ίδια τιμή, ακόμα και αν δεν αναφέρονται στο ίδιο αντικείμενο,
  • ο equal? συγκρίνει δομές δεδομένων όπως οι λίστες, τα διανύσματα και οι συμβολοσειρές για να βρει αν έχουν σύμφωνη (congruent) δομή και περιεχόμενα ίσα σύμφωνα με τον eqv?.(R5RS sec. 6.1)[3]

Στη Scheme υπάρχουν επίσης λειτουργίες ισοδυναμίας εξαρτώμενης από τους τύπους: ο string=? και ο string-ci=? συγκρίνουν δύο συμβολοσειρές (στην τελευταία περίπτωση χωρίς να λαμβάνεται υπόψη συμφωνία πεζών-κεφαλαίων), ο char=? και ο char-ci=? συγκρίνουν χαρακτήρες και ο = συγκρίνει αριθμούς.[3]

Σχόλια[Επεξεργασία | επεξεργασία κώδικα]

Δείτε επίσης: Σχόλιο (προγραμματισμός)

Μέχρι το πρότυπο R5RS, τα πρότυπα σχόλια στη Scheme εισάγονταν με ελληνικό ερωτηματικό (";"), το οποίο έκανε την υπόλοιπη γραμμή που ακολουθούσε αόρατη στη Scheme. Διάφορες υλοποιήσεις έχουν υποστηρίξει εναλλακτικές συμβάσεις που επιτρέπουν στα σχόλια να καταλαμβάνουν πάνω από μια γραμμές και το πρότυπο R6RS επιτρέπει δύο από αυτές: μια ολόκληρη s-έκφραση μπορεί να μετατραπεί σε σχόλιο αν στην αρχή της προστεθεί το #; (αυτό εισήχθηκε στο SRFI 62[18]) και ένα σχόλιο πολλών γραμμών ή "σχόλιο-ενότητα" ("block comment") μπορεί να δημιουργηθεί αν περικλειστεί το κείμενο ανάμεσα στα #| και |#.

Είσοδος/έξοδος[Επεξεργασία | επεξεργασία κώδικα]

Η είσοδος και η έξοδος της Scheme βασίζονται στον τύπο δεδομένων θύρα (port). (R5RS sec 6.6)[3] Το 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.[19] Το πρότυπο 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, με την οποία έχει και το ίδιο όνομα.[20]

Ορισμός ξανά των πρότυπων διαδικασιών[Επεξεργασία | επεξεργασία κώδικα]

Οι διαδικασίες στη Scheme δεσμεύονται σε μεταβλητές. Το πρότυπο της γλώσσας στο R5RS επίσημα δηλώνει ότι τα προγράμματα μπορούν να αλλάξουν τις δεσμεύσεις των μεταβλητών των ενσωματωμένων διαδικασιών, πρακτικά ορίζοντάς τις πάλι (R5RS, "Language changes"[3]). Για παράδειγμα, κάποιος μπορεί να επεκτείνει τη + ώστε να δέχεται συμβολοσειρές εκτός από αριθμούς, ορίζοντάς την πάλι:

(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)[4] Για αυτόν το λόγο, ο ορισμός ξανά των βασικών διαδικασιών μέσω τροποποίησης απαγορεύεται. Αντί για αυτό, είναι δυνατό να εισαχθεί μια διαφορετική διαδικασία με το ίδιο όνομα με μια πρότυπη, κάτι που στην πραγματικότητα δε διαφέρει πολύ από την τεχνική που περιγράφηκε παραπάνω.

Ορολογία και συμβάσεις ονοματοδοσίας[Επεξεργασία | επεξεργασία κώδικα]

Στην Πρότυπη Scheme, οι διαδικασίες που μετατρέπουν από έναν τύπο δεδομένων σε έναν άλλο περιέχουν στο όνομά τους την ακολουθία χαρακτήρων "->", οι προτάσεις ιδιοτήτων (predicates) λήγουν σε "?", και οι διαδικασίες που αλλάζουν την τιμή δεδομένων ήδη δεσμευμένων στη μνήμη λήγουν σε "!". Αυτές οι συμβάσεις συχνά ακολουθούνται από τους προγραμματιστές της Scheme.

Σε επίσημο λόγο, όπως στα πρότυπα της Scheme, η λέξη "διαδικασία" ("procedure") χρησιμοποιείται αντί της "συνάρτησης" ("function") για να αναφέρεται σε μια λ-έκφραση ή σε μια πρωτογενή διαδικασία. Στον κανονικό λόγο οι λέξεις "διαδικασία" και "συνάρτηση" χρησιμοποιούνται εξίσου. Η εφαρμογή διαδικασίας μερικές φορές ονομάζεται επίσημα συνδυασμός (combination).

Όπως και σε άλλες διαλέκτους της Lisp, ο όρος "thunk" χρησιμοποιείται στη Scheme για να αναφέρεται σε μια διαδικασία χωρίς ορίσματα. Ο όρος "σωστή αναδρομή ουράς" ("proper tail recursion") αναφέρεται στην ιδιότητα που έχουν όλες οι υλοποιήσεις της Scheme, της εφαρμογής βελτιστοποίησης κλήσης ουράς ("tail-call optimization") ώστε να υποστηρίζουν άπειρο αριθμό ενεργών κλήσεων ουράς.

Η μορφή των τίτλων των εγγράφων των προτύπων από το R3RS, "Revisedn Report on the Algorithmic Language Scheme", είναι αναφορά στον τίτλο του εγγράφου του προτύπου της ALGOL 60, "Revised Report on the Algorithmic Language Algol 60," και η σελίδα με την περίληψη (Summary) του R3RS μοιάζει με αυτήν της Αναφοράς της ALGOL 60.[21][22]

Πρότυπες μορφές και διαδικασίες[Επεξεργασία | επεξεργασία κώδικα]

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

Πρότυπες μορφές[Επεξεργασία | επεξεργασία κώδικα]

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

Οι μορφές που σημειώνονται με "L" στον πίνακα θεωρούνται παραγόμενες μορφές "βιβλιοθήκης" στο πρότυπο και συχνά υλοποιούνται στην πράξη ως μακροεντολές με τη χρήση βασικότερων μορφών, διευκολύνοντας την υλοποίηση σε σχέση με άλλες γλώσσες.

Πρότυπες μορφές στη γλώσσα R5RS Scheme
Σκοπός Μορφές
Ορισμός define
Δομές δέσμευσης lambda, do (L), let (L), let* (L), letrec (L)
Αποτίμηση υπό συνθήκη if, cond (L), case (L), and (L), or (L)
Ακολουθιακή αποτίμηση begin (L)
Επαναληψη lambda, do (L), named let (L)
Επέκταση της σύνταξης define-syntax, let-syntax, letrec-syntax, syntax-rules (R5RS), syntax-case (R6RS)
Παράθεση (quoting) quote('), unquote(,), quasiquote(`), unquote-splicing(,@)
Ανάθεση set!
Καθυστερημένη αποτίμηση delay (L)

Πρότυπες διαδικασίες[Επεξεργασία | επεξεργασία κώδικα]

Οι παρακάτω δύο πίνακες περιγράφουν τις πρότυπες διαδικασίες της R5RS Scheme. Το R6RS είναι πολύ πιο εκτεταμένο για να δοθεί μια παρόμοια περιληπτική περιγραφή.

Κάποιες διαδικασίες εμφανίζονται σε παραπάνω από μια γραμμές γιατί δε μπορούν να καταταγούν σε μια μοναδική λειτουργία της γλώσσας.

Πρότυπες διαδικασίες της γλώσσας R5RS Scheme
Σκοπός Διαδικασίες
Κατασκευή δομών δεδομένων vector, make-vector, make-string, list
Προτάσεις ισοδυναμίας eq?, eqv?, equal?, string=?, string-ci=?, char=?, char-ci=?
Μετατροπή τύπου vector->list, list->vector, number->string, string->number, symbol->string, string->symbol, char->integer, integer->char, string->list, list->string
Αριθμοί Δείτε ξεχωριστό πίνακα
Συμβολοσειρές string?, make-string, string, string-length, string-ref, string-set!, string=?, string-ci=?, string<? string-ci<?, string<=? string-ci<=?, string>? string-ci>?, string>=? string-ci>=?, substring, string-append, string->list, list->string, string-copy, string-fill!
Χαρακτήρες char?, char=?, char-ci=?, char<? char-ci<?, char<=? char-ci<=?, char>? char-ci>?, char>=? char-ci>=?, char-alphabetic?, char-numeric?, char-whitespace?, char-upper-case?, char-lower-case?, char->integer, integer->char, char-upcase, char-downcase
Διανύσματα make-vector, vector, vector?, vector-length, vector-ref, vector-set!, vector->list, list->vector, vector-fill!
Σύμβολα symbol->string, string->symbol, symbol?
Ζεύγη και λίστες pair?, cons, car, cdr, set-car!, set-cdr!, null?, list?, list, length, append, reverse, list-tail, list-ref, memq. memv. member, assq, assv, assoc, list->vector, vector->list, list->string, string->list
Μοναδιαίες προτάσεις boolean?, pair?, symbol?, number?, char?, string?, vector?, port?, procedure?
Συνέχειες call-with-current-continuation (call/cc), values, call-with-values, dynamic-wind
Περιβάλλοντα eval, scheme-report-environment, null-environment, interaction-environment (optional)
Είσοδος/έξοδος display, newline, read, write, read-char, write-char, peek-char, char-ready?, eof-object? open-input-file, open-output-file, close-input-port, close-output-port, input-port?, output-port?, current-input-port, current-output-port, call-with-input-file, call-with-output-file, with-input-from-file(optional), with-output-to-file(optional)
Διεπαφή συστήματος load (optional), transcript-on (optional), transcript-off (optional)
Καθυστερημένη αποτίμηση force
Συναρτησιακός προγραμματισμός procedure?, apply, map, for-each
Τιμές αλήθειας boolean? not}}

Οι διαδικασίες συμβολοσειρών και χαρακτήρων που περιέχουν το "-ci" στο όνομά τους εκτελούν συγκρίσεις χωρίς να λαμβάνουν υπόψη τους τη συμφωνία κεφαλαίων-πεζών (θεωρούν τους αντίστοιχους χαρακτήρες ίσους).

Πρότυπες αριθμητικές διαδικασίες για τη γλώσσα R5RS Scheme
Σκοπός Διαδικασίες
Βασικοί αριθμητικοί τελεστές +, -. *, /, abs, quotient, remainder, modulo, gcd, lcm, expt, sqrt
Ρητοί αριθμοί numerator, denominator, rational?, rationalize
Στρογγυλοποίηση floor, ceiling, truncate, round
Ακρίβεια inexact->exact, exact->inexact, exact?, inexact?
Ανισότητες <. <=, >, >=
Άλλες προτάσεις zero?, negative?, positive? odd? even?
Ελάχιστο και μέγιστο max. min
Τριγωνομετρία sin, cos, tan, asin, acos, atan
Εκθετικές συναρτήσεις exp, log
Μιγαδικοί αριθμοί make-rectangular, make-polar, real-part, imag-part, magnitude, angle, complex?
Είσοδος-έξοδος number->string, string->number
Προτάσεις τύπων integer?, rational?, real?, complex?, number?}}

Η υλοποίηση του - και του / που δέχονται παραπάνω από δύο παραμέτρους ορίζεται αλλά αφήνεται προαιρετική στο R5RS.

Αιτήματα για Υλοποίηση στη Scheme - μεταφέρσιμες επεκτάσεις του προτύπου[Επεξεργασία | επεξεργασία κώδικα]

Λόγω του μινιμαλισμού της Scheme, πολλές κοινές διαδικασίες και συντακτικές μορφές δεν ορίζονται από το πρότυπο. Για να κρατηθεί η βασική γλώσσα μικρή αλλά να είναι εύκολη η προτυποποίηση επεκτάσεων, η κοινότητα της Scheme ακολουθεί μια διαδικασία "Αιτήματος Υλοποίησης στη Scheme" ("Scheme Request for Implementation", SRFI), με την οποία ορίζονται βιβλιοθήκες επέκτασης μέσω προσεκτικής συζήτησης προτάσεων επέκτασης, κάτι που βελτιώνει τη μεταφερσιμότητα του κώδικα. Πολλά από τα SRFI υποστηρίζονται από όλες ή από τις περισσότερες υλοποιήσεις της Scheme.

Μια πλήρης λίστα από SRFI που έχουν γίνει αποδεκτά σε τελικό στάδιο είναι διαθέσιμη στο http://srfi.schemers.org/final-srfis.html.

Υλοποιήσεις[Επεξεργασία | επεξεργασία κώδικα]

Η κομψή και μινιμαλιστική σχεδίαση έχουν κάνει τη Scheme δημοφιλή στόχο για σχεδιαστές γλωσσών, ερασιτέχνες και εκπαιδευτικούς, και λόγω του μικρού μεγέθους του μέσου διερμηνέα της είναι επίσης δημοφιλής για ενσωματωμένα συστήματα και ως γλώσσα σεναρίων. Αυτό έχει ως αποτέλεσμα πολλές υλοποιήσεις,[23]. Οι πιο πολλές διαφέρουν μεταξύ τους τόσο που η μεταφορά προγραμμάτων από τη μια στην άλλη είναι αρκετά δύσκολη και το μικρό μέγεθος της βασικής γλώσσας σημαίνει ότι είναι εξαιρετικά δύσκολο να γραφεί ένα χρήσιμο αλλά πολύπλοκο πρόγραμμα σε πρότυπη και μεταφέρσιμη 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.[4]

Οι νεότερες εκδόσεις διάφορων υλοποιήσεων της Scheme, π.χ. η Ikarus, η Larceny, η Racket και η Ypsilon υποστηρίζουν το πρότυπο R6RS. Υπάρχει μια μεταφέρσιμη υλοποίηση αναφοράς των προτεινόμενων βιβλιοθηκών που πρόκειται να αλλάξουν για το R6RS, που ονομάζεται psyntax, η οποία μπορεί να φορτώνει και να εκκινεί τον εαυτό της σωστά με πολλές παλαιότερες υλοποιήσεις της Scheme.[24]

Το R6RS εισάγει αρκετές σημαντικές αλλαγές στη γλώσσα.[25] Ο πηγαίος κώδικας ορίζεται πια σε Unicode, και ένα μεγαλύτερο υποσύνολο των χαρακτήρων Unicode μπορεί να εμφανιστεί σε σύμβολα της Scheme και σε αναγνωριστικά, ενώ υπάρχουν και άλλες μικρές αλλαγές στους λεκτικούς κανόνες. Τα δεδομένα χαρακτήρων επίσης ορίζονται σε Unicode. Πολλές πρότυπες διαδικασίες έχουν μετακινηθεί στις νέες πρότυπες διαδικασίες, οι οποίες με τη σειρά τους αποτελούν μια μεγάλη επέκταση του προτύπου, περιέχοντας διαδικασίες και συντακτικές μορφές που παλαιότερα δεν ήταν μέρος του προτύπου. Για την υποστήριξη των βιβλιοθηκών και τη δημιουργία περισσότερων βιβλιοθηκών, εισάγεται ένα νέο σύστημα μονάδων κώδικα ενώ το πρότυπο περιγράφει και συστήματα για το χειρισμό εξαιρέσεων. Το syntax-rules έχει αντικατασταθεί από ένα ισχυρότερο εργαλείο συντακτικής αφαίρεσης (syntax-case), το οποίο επιτρέπει τη χρήση ολόκληρης της Scheme κατά το χρόνο επέκτασης των μακροεντολών. Οι υλοποιήσεις που συμφωνούν με το πρότυπο πρέπει να υποστηρίζουν τον πλήρη αριθμητικό πύργο της Scheme, και η σημασιολογία των αριθμών έχει επεκταθεί, κυρίως για την υποστήριξη του προτύπου IEEE 754 για την αναπαράσταση αριθμών κινητής υποδιαστολής.

Το νέο πρότυπο έχει προκαλέσει κάποιες αντιδράσεις γιατί εμφανίζεται να απομακρύνεται από τη μινιμαλιστική φιλοσοφία των προηγούμενων.[26][27] Τον Αύγουστο του 2009, η αρμόδια επιτροπή της Scheme (Scheme Steering Committee) που επιβλέπει τη διαδικασία της προτυποποίησης ανακοίνωσε την πρόθεσή της να συστήσει το διαχωρισμό της γλώσσας σε δύο γλώσσες: μια μεγάλη και σύγχρονη γλώσσα προγραμματισμού για προγραμματιστές, και ένα υποσύνολο της μεγάλης αυτής έκδοσης που να διατηρεί το μινιμαλισμό που επιθυμούν οι εκπαιδευτικοί και όσοι υλοποιούν απλά τη γλώσσα.[1]

Χρήση[Επεξεργασία | επεξεργασία κώδικα]

Η Scheme χρησιμοποιείται από αρκετά[28] εκπαιδευτικά ιδρύματα και πολλά μαθήματα εισαγωγής στην επιστήμη των υπολογιστών χρησιμοποιούν τη Scheme μαζί με το βιβλίο Structure and Interpretation of Computer Programs (SICP).[29] Τα τελευταία 12 χρόνια, η PLT λειτουγεί το εγχείρημα TeachScheme!, το οποίο έχει φέρει σε επαφή περίπου 600 καθηγητές της δευτεροβάθμιας εκπαίδευσης και χιλιάδες μαθητές με τις βασικές αρχές του προγραμματισμού Scheme. Το παλιό μάθημα εισαγωγής στον προγραμματισμού στο MIT (6.001) χρησιμοποιούσε τη Scheme στη διδασκαλία του.[30] Αν και το 6.001 έχει αντικατασταθεί από πιο σύγχρονα μαθήματα, το SICP εξακολουθεί να διδάσκεται στο MIT.[31] Το βιβλίο How to Design Programs του Matthias Felleisen χρησιμοποιείται από κάποια ιδρύματα ανώτατης εκπαίδευσης για τα μαθήματα εισαγωγής στον προγραμματισμό. [32] [33]

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

Υπάρχουν σχετικά λίγα παραδείγματα πραγματικής χρήσης της Scheme[34] για μη-εκπαιδευτικούς σκοπούς. Η Document Style Semantics and Specification Language (DSSSL), που ορίζει φύλα στυλ της SGML, χρησιμοποιεί ένα υποσύνολο της Scheme.[35] Επιπλέον, το γνωστό πρόγραμμα επεξεργασίας εικόνας ανοιχτού κώδικα GIMP χρησιμοποιεί τη Scheme ως γλώσσα σεναρίων.[36] Η Guile έχει υιοθετηθεί από το εγχείρημα GNU ως η επίσημη γλώσσα σεναρίων και η υλοποίηση αυτή της Scheme έχει ενσωματωθεί σε εφαρμογές όπως το GNU LilyPond και GnuCash, λειτουργώντας ως γλώσσα σεναρίων για επεκτάσεις. Παρομοίως η Guile ήταν η γλώσσα σεναρίων του γραφικού περιβάλλοντος GNOME,[37] και το GNOME ακόμα έχει ένα εγχείρημα που παρέχει συνδέσεις από Guile στις βιβλιοθήκες του.[38] Η Elk Scheme χρησιμοποιείται από τη Synopsys ως γλώσσα σεναρίων για τα εργαλεία TCAD της.[39] Ο Shiro Kawai, προγραμματιστής της ταινίας Final Fantasy: The Spirits Within, χρησιμοποίησε τη Scheme ως γλώσσα σεναρίων για τον έλεγχο της μηχανής φωτοαπόδοσης πραγματικού χρόνου.[40] Το App Inventor του Google για το Android χρησιμοποιεί τη Scheme, ενώ η Kawa χρησιμοποιείται για τη μεταγλώττιση κώδικα Scheme σε κώδικα byte για την Εικονική Μηχανή της Java που εκτελείται στις συσκευές Android.[41]

Εξωτερικοί σύνδεσμοι[Επεξεργασία | επεξεργασία κώδικα]

Παραπομπές[Επεξεργασία | επεξεργασία κώδικα]

  1. 1,0 1,1 Will Clinger, Marc Feeley, Chris Hanson, Jonathan Rees and Olin Shivers (2009-08-20). «Position Statement, draft». Scheme Steering Committee. http://scheme-reports.org/2009/position-statement.html. Ανακτήθηκε στις 2009-10-20. 
  2. 2,0 2,1 1178-1990 (Reaff 2008) IEEE Standard for the Scheme Programming Language. IEEE part number STDPD14209, unanimously reaffirmed at a meeting of the IEEE-SA Standards Board Standards Review Committee (RevCom), March 26, 2008 (item 6.3 on minutes), reaffirmation minutes accessed October 2009. NOTE: this document is only available for purchase from IEEE and is not available online at the time of writing (2009).
  3. 3,00 3,01 3,02 3,03 3,04 3,05 3,06 3,07 3,08 3,09 3,10 3,11 3,12 3,13 3,14 3,15 3,16 3,17 Richard Kelsey, William Clinger, Jonathan Rees et al. (August 1998). "Revised5 Report on the Algorithmic Language Scheme". Higher-Order and Symbolic Computation 11 (1): 7–105. doi:10.1023/A:1010051815785. http://www.schemers.org/Documents/Standards/R5RS/. 
  4. 4,0 4,1 4,2 4,3 Michael Sperber, R. Kent Dybvig, Matthew Flatt, Anton Van Straaten et al. (August 2007). «Revised6 Report on the Algorithmic Language Scheme (R6RS)». Scheme Steering Committee. http://www.r6rs.org/. Ανακτήθηκε στις 2009-10-20. 
  5. «R6RS ratification-voting results». Scheme Steering Committee. 2007-08-13. http://www.r6rs.org/ratification/results.html. Ανακτήθηκε στις 2009-10-20. 
  6. Common LISP: The Language, 2nd Ed., Guy L. Steele Jr. Digital Press; 1981. ISBN 978-1-55558-041-4. "Common Lisp is a new dialect of Lisp, a successor to MacLisp, influenced strongly by ZetaLisp and to some extent by Scheme and InterLisp."
  7. 7,0 7,1 7,2 7,3 Gerald Jay Sussman and Guy L. Steele, Jr. (December 1998). "The First Report on Scheme Revisited" (PDF). Higher-Order and Symbolic Computation 11 (4): 399–404. doi:10.1023/A:1010079421970. ISSN 1388-3690. http://www.brics.dk/~hosc/local/HOSC-11-4-pp399-404.pdf. Ανακτήθηκε στις 2006-06-19. 
  8. Είναι γεγονός ότι η υλοποίηση Scheme 48 ονομάστηκε έτσι γιατί ο διερμηνέας αναπτύχθηκε από τους Richard Kelsey και Jonathan Rees μέσα σε 48 ώρες μεταξύ της 6ης και της 7ης Αυγούστου του 1986.Richard Kelsey, Jonathan Rees, Mike Sperber (2008-01-10). «The Incomplete Scheme 48 Reference Manual for release 1.8». Jonathan Rees, s48.org. http://s48.org/1.8/manual/manual.html. Ανακτήθηκε στις 2009-10-20. 
  9. Όπως αναφέρεται στο R5RS (R5RS sec. 3.1): "The most fundamental of the variable binding constructs is the lambda expression, because all other variable binding constructs can be explained in terms of lambda expressions."
  10. 10,0 10,1 Gerald Jay Sussman and Guy Lewis Steele, Jr. (December 1975). "Scheme: An Interpreter for Extended Lambda Calculus" (postscript or PDF). AI Memos (MIT AI Lab) AIM-349. http://library.readscheme.org/page1.html. Ανακτήθηκε στις 2009-10-20 
  11. Joel Moses (June 1970) (pdf), The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Called the Environment Problem, AI Memo 199, http://dspace.mit.edu/handle/1721.1/5854, ανακτήθηκε στις 2009-10-27, «A useful metaphor for the difference between FUNCTION and QUOTE in LISP is to think of QUOTE as a porous or an open covering of the function since free variables escape to the current environment. FUNCTION acts as a closed or nonporous covering (hence the term "closure" used by Landin). Thus we talk of "open" Lambda expressions (functions in LISP are usually Lambda expressions) and "closed" Lambda expressions. [...] My interest in the environment problem began while Landin, who had a deep understanding of the problem, visited MIT during 1966-67. I then realized the correspondence between the FUNARG lists which are the results of the evaluation of "closed" Lambda expressions in LISP and ISWIM's Lambda Closures.» 
  12. Gerald Jay Sussman and Guy Lewis Steele, Jr. (March 1976). "Lambda: The Ultimate Imperative" (postscript or PDF). AI Memos (MIT AI Lab) AIM-353. http://library.readscheme.org/page1.html. Ανακτήθηκε στις 2009-10-20 
  13. John David Stone (1999-08-30). «SRFI 8: receive: Binding to multiple values». The SRFI Editors, schemers.org. http://srfi.schemers.org/srfi-8/srfi-8.html. Ανακτήθηκε στις 2009-10-20. 
  14. Gabriel, Richard P.; Pitman, Kent (1988). "Technical Issues of Separation in Function Cells and Value Cells". Lisp and Symbolic Computation 1 (1): σελ. 81–101. June 1988. doi:10.1007/BF01806178. http://www.nhplace.com/kent/Papers/Technical-Issues.html. Ανακτήθηκε στις 2009-10-14 
  15. 15,0 15,1 Philip L. Bewig (2008-01-24). «SRFI 41: Streams». The SRFI Editors, schemers.org. http://srfi.schemers.org/srfi-41/srfi-41.html. Ανακτήθηκε στις 2009-10-20. 
  16. William Clinger and Jonathan Rees, editors (1991). "Revised4 Report on the Algorithmic Language Scheme". ACM Lisp Pointers 4 (3): 1–55. http://www.cs.indiana.edu/scheme-repository/R4RS/r4rs_toc.html. Ανακτήθηκε στις 2009-10-20 
  17. Jonathan Rees, The Scheme of Things The June 1992 Meeting (postscript), in Lisp Pointers, V(4), October-December 1992. retrieved 2009-10-20
  18. Taylor Campbell (2005-07-21). «SRFI 62: S-expression comments». The SRFI Editors, schemers.org. http://srfi.schemers.org/srfi-62/srfi-62.html. Ανακτήθηκε στις 2009-10-20. 
  19. William D Clinger (1999-07-01). «SRFI 6: Basic String Ports». The SRFI Editors, schemers.org. http://srfi.schemers.org/srfi-6/srfi-6.html. Ανακτήθηκε στις 2009-10-20. 
  20. Scott G. Miller (2002-06-25). «SRFI 28: Basic Format Strings». The SRFI Editors, schemers.org. http://srfi.schemers.org/srfi-28/srfi-28.html. Ανακτήθηκε στις 2009-10-20. 
  21. J.W. Backus, F.L. Bauer, J.Green, C. Katz, J. McCarthy P. Naur, et al (January-April, 1960). "Revised Report on the Algorithmic Language Algol 60". Numerische Mathematik, Communications of the ACM, and Journal of the British Computer Society. http://www.masswerk.at/algol60/report.htm. Ανακτήθηκε στις 2009-10-20 
  22. Jonathan Rees and William Clinger (Editors), Hal Abelson, R. K. Dybvig et al. (December 1986). "Revised(3) Report on the Algorithmic Language Scheme, (Dedicated to the Memory of ALGOL 60)". ACM SIGPLAN Notices 21 (12): 37–79. http://groups.csail.mit.edu/mac/ftpdir/scheme-reports/r3rs-html/r3rs_toc.html. Ανακτήθηκε στις 2009-10-20 
  23. 75 από τις οποίες δημοσιεύονται στο «scheme-faq-standards». Community Scheme Wiki. 2009-06-25. http://community.schemewiki.org/?scheme-faq-standards#implementations. Ανακτήθηκε στις 2009-10-20. 
  24. Abdulaziz Ghuloum (2007-10-27). «R6RS Libraries and syntax-case system (psyntax)». Ikarus Scheme. https://www.cs.indiana.edu/~aghuloum/r6rs-libraries/. Ανακτήθηκε στις 2009-10-20. 
  25. «Revised^6 Report on the Algorithmic Language Scheme, Appendix E: language changes». Scheme Steering Committee. 2007-09-26. http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-19.html#node_chap_E. Ανακτήθηκε στις 2009-10-20. 
  26. «R6RS Electorate». Scheme Steering Committee. 2007. http://www.r6rs.org/ratification/electorate.html. Ανακτήθηκε στις 2009-10-20. 
  27. Marc Feeley (compilation) (2007-10-26). «Implementors' intentions concerning R6RS». Scheme Steering Committee, r6rs-discuss mailing list. http://lists.r6rs.org/pipermail/r6rs-discuss/2007-October/003351.html. Ανακτήθηκε στις 2009-10-20. 
  28. Ed Martin (2009-07-20). «List of Scheme-using schools». Schemers Inc.. http://www.schemers.com/schools.html. Ανακτήθηκε στις 2009-10-20. 
  29. «List of SICP-using schools». MIT Press. 1999-01-26. http://mitpress.mit.edu/sicp/adopt-list.html. Ανακτήθηκε στις 2009-10-20. 
  30. Eric Grimson (Spring, 2005). «6.001 Structure and Interpretation of Computer Programs». MIT Open Courseware. http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-001Spring-2005/CourseHome/index.htm. Ανακτήθηκε στις 2009-10-20. 
  31. Alex Vandiver, Nelson Elhage, et al (January 2009). «6.184 - Zombies drink caffeinated 6.001». MIT CSAIL. http://web.mit.edu/alexmv/6.001/. Ανακτήθηκε στις 2009-10-20. 
  32. CS 2500: Fundamentals of Computer Science I, Northeastern University
  33. CS 1101: Introduction to Program Design (A05): course software, Worcester Polytechnic Institute
  34. , βλ. What is Scheme used for? στο «scheme-faq-general». Community Scheme Wiki. 2009-03-21. http://community.schemewiki.org/?scheme-faq-general. Ανακτήθηκε στις 2009-10-20. 
  35. Robin Cover (2002-02-25). «DSSSL - Document Style Semantics and Specification Language. ISO/IEC 10179:1996». Cover Pages. http://xml.coverpages.org/dsssl.html. Ανακτήθηκε στις 2009-10-20. 
  36. "The major scripting language for the GIMP that has been attached to it today is Scheme." From Dov Grobgeld (2002). «The GIMP Basic Scheme Tutorial». The GIMP Team. http://www.gimp.org/tutorials/Basic_Scheme/. Ανακτήθηκε στις 2009-10-20. 
  37. Todd Graham Lewis, David Zoll, Julian Missig (2002). «GNOME FAQ from Internet Archive». The Gnome Team, gnome.org. http://web.archive.org/web/20000522010523/http://www.gnome.org/gnomefaq/html/x930.html. Ανακτήθηκε στις 2009-10-20. 
  38. «guile-gnome». Free Software Foundation. http://www.gnu.org/software/guile-gnome/. Ανακτήθηκε στις 2009-10-20. 
  39. Laurence Brevard (2006-11-09). «Synopsys MAP-inSM Program Update: EDA Interoperability Developers’ Forum» (pdf). Synopsis Inc. http://www.synopsys.com/community/interoperability/documents/devforum_pres/2006nov/milkywaysession_mapin_overview.pdf. Ανακτήθηκε στις 2009-10-20. 
  40. Kawai, Shiro (Οκτώβριος 2002). "Gluing Things Together - Scheme in the Real-time CG Content Production". Proceedings of the First International Lisp Conference, San Francisco: 342–348. http://practical-scheme.net/docs/ILC2002.html. Ανακτήθηκε στις 2009-10-20 
  41. Bill Magnuson, Hal Abelson, and Mark Friedman (2009-08-11). «Under the Hood of App Inventor for Android». Google Inc, Official Google Research blog. http://googleresearch.blogspot.com/2009/08/under-hood-of-app-inventor-for-android.html. Ανακτήθηκε στις 2009-10-20. 

Περαιτέρω διάβασμα[Επεξεργασία | επεξεργασία κώδικα]

Wikibooks logo
Τα αγγλικά Βικιβιβλία έχουν βιβλία που έχουν σχέση με τη:
Στο λήμμα αυτό έχει ενσωματωθεί κείμενο από το λήμμα Scheme (programming language) της Αγγλικής Βικιπαίδειας, η οποία διανέμεται υπό την GNU FDL και την CC-BY-SA 3.0. (ιστορικό/συντάκτες).