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) που περιέχουν βασικότερες (κυρίως) λ-μορφές.[3][9]
- Βασικές μορφές: 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" στον πίνακα θεωρούνται παραγόμενες μορφές "βιβλιοθήκης" στο πρότυπο και συχνά υλοποιούνται στην πράξη ως μακροεντολές με τη χρήση βασικότερων μορφών, διευκολύνοντας την υλοποίηση σε σχέση με άλλες γλώσσες.
Σκοπός | Μορφές |
---|---|
Ορισμός | 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 είναι πολύ πιο εκτεταμένο για να δοθεί μια παρόμοια περιληπτική περιγραφή.
Κάποιες διαδικασίες εμφανίζονται σε παραπάνω από μια γραμμές γιατί δε μπορούν να καταταγούν σε μια μοναδική λειτουργία της γλώσσας.
Σκοπός | Διαδικασίες |
---|---|
Κατασκευή δομών δεδομένων | 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" στο όνομά τους εκτελούν συγκρίσεις χωρίς να λαμβάνουν υπόψη τους τη συμφωνία κεφαλαίων-πεζών (θεωρούν τους αντίστοιχους χαρακτήρες ίσους).
Σκοπός | Διαδικασίες |
---|---|
Βασικοί αριθμητικοί τελεστές | +, -. *, /, 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]
Εξωτερικοί σύνδεσμοι
[Επεξεργασία | επεξεργασία κώδικα]- Η τελευταία έκδοση του προτύπου της Scheme: R6RS (Αγγλικά)
- Schemers.org (Αγγλικά)
Παραπομπές
[Επεξεργασία | επεξεργασία κώδικα]- ↑ 1,0 1,1 Will Clinger· Marc Feeley· Chris Hanson· Jonathan Rees· Olin Shivers (20 Αυγούστου 2009). «Position Statement, draft». Scheme Steering Committee. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ 2,0 2,1 1178-1990 (Reaff 2008) IEEE Standard for the Scheme Programming Language. IEEE part number STDPD14209, unanimously reaffirmed Αρχειοθετήθηκε 2010-07-06 στο Wayback Machine. at a meeting of the IEEE-SA Standards Board Standards Review Committee (RevCom), 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,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. (Αύγουστος 1998). «Revised5 Report on the Algorithmic Language Scheme». Higher-Order and Symbolic Computation 11 (1): 7–105. doi:. http://www.schemers.org/Documents/Standards/R5RS/.
- ↑ 4,0 4,1 4,2 4,3 Michael Sperber· R. Kent Dybvig· Matthew Flatt· Anton Van Straaten· Richard Kesley· William Clinger· Jonathan Rees, επιμ. (Αύγουστος 2007). «Revised6 Report on the Algorithmic Language Scheme (R6RS)». Scheme Steering Committee. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ «R6RS ratification-voting results». Scheme Steering Committee. 13 Αυγούστου 2007. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ 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,0 7,1 7,2 7,3 Gerald Jay Sussman and Guy L. Steele, Jr. (Δεκέμβριος 1998). «The First Report on Scheme Revisited» (PDF). Higher-Order and Symbolic Computation 11 (4): 399–404. doi: . ISSN 1388-3690. Αρχειοθετήθηκε από το πρωτότυπο στις 2006-06-15. https://web.archive.org/web/20060615225746/http://www.brics.dk/~hosc/local/HOSC-11-4-pp399-404.pdf. Ανακτήθηκε στις 19 Ιουνίου 2006.
- ↑ Είναι γεγονός ότι η υλοποίηση Scheme 48 ονομάστηκε έτσι γιατί ο διερμηνέας αναπτύχθηκε από τους Richard Kelsey και Jonathan Rees μέσα σε 48 ώρες μεταξύ της 6ης και της 7ης Αυγούστου του 1986.Richard Kelsey· Jonathan Rees· Mike Sperber (10 Ιανουαρίου 2008). «The Incomplete Scheme 48 Reference Manual for release 1.8». Jonathan Rees, s48.org. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Όπως αναφέρεται στο 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,0 10,1 Gerald Jay Sussman and Guy Lewis Steele, Jr. (Δεκέμβριος 1975). «Scheme: An Interpreter for Extended Lambda Calculus» (postscript or PDF). AI Memos (MIT AI Lab) AIM-349. Αρχειοθετήθηκε από το πρωτότυπο στις 2016-05-10. https://web.archive.org/web/20160510140804/http://library.readscheme.org/page1.html. Ανακτήθηκε στις 20 Οκτωβρίου 2009
- ↑ Joel Moses (1970), 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, ανακτήθηκε στις 27 Οκτωβρίου 2009
- ↑ Gerald Jay Sussman and Guy Lewis Steele, Jr. (Μάρτιος 1976). «Lambda: The Ultimate Imperative» (postscript or PDF). AI Memos (MIT AI Lab) AIM-353. Αρχειοθετήθηκε από το πρωτότυπο στις 2016-05-10. https://web.archive.org/web/20160510140804/http://library.readscheme.org/page1.html. Ανακτήθηκε στις 20 Οκτωβρίου 2009
- ↑ John David Stone (30 Αυγούστου 1999). «SRFI 8: receive: Binding to multiple values». The SRFI Editors, schemers.org. Αρχειοθετήθηκε από το πρωτότυπο στις 10 Οκτωβρίου 2010. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Gabriel, Richard P.; Pitman, Kent (1988). «Technical Issues of Separation in Function Cells and Value Cells». Lisp and Symbolic Computation 1 (1): σελ. 81–101. Ιούνιος 1988. doi:. http://www.nhplace.com/kent/Papers/Technical-Issues.html. Ανακτήθηκε στις 14 Οκτωβρίου 2009
- ↑ 15,0 15,1 Philip L. Bewig (24 Ιανουαρίου 2008). «SRFI 41: Streams». The SRFI Editors, schemers.org. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ 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. Ανακτήθηκε στις 20 Οκτωβρίου 2009
- ↑ Jonathan Rees, The Scheme of Things The June 1992 Meeting Αρχειοθετήθηκε 2011-07-16 στο Wayback Machine. (postscript), in Lisp Pointers, V(4), Οκτώβριος-Δεκέμβριος 1992. retrieved 20 Οκτωβρίου 2009
- ↑ Taylor Campbell (21 Ιουλίου 2005). «SRFI 62: S-expression comments». The SRFI Editors, schemers.org. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ William D Clinger (1 Ιουλίου 1999). «SRFI 6: Basic String Ports». The SRFI Editors, schemers.org. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Scott G. Miller (25 Ιουνίου 2002). «SRFI 28: Basic Format Strings». The SRFI Editors, schemers.org. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ J.W. Backus, F.L. Bauer, J.Green, C. Katz, J. McCarthy P. Naur, et al (Ιανουάριος-Απρίλιος 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. Ανακτήθηκε στις 20 Οκτωβρίου 2009
- ↑ Jonathan Rees and William Clinger (Editors), Hal Abelson, R. K. Dybvig et al. (Δεκέμβριος 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. Ανακτήθηκε στις 20 Οκτωβρίου 2009
- ↑ 75 από τις οποίες δημοσιεύονται στο «scheme-faq-standards». Community Scheme Wiki. 25 Ιουνίου 2009. Αρχειοθετήθηκε από το πρωτότυπο στις 18 Φεβρουαρίου 2010. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Abdulaziz Ghuloum (27 Οκτωβρίου 2007). «R6RS Libraries and syntax-case system (psyntax)». Ikarus Scheme. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ «Revised^6 Report on the Algorithmic Language Scheme, Appendix E: language changes». Scheme Steering Committee. 26 Σεπτεμβρίου 2007. Αρχειοθετήθηκε από το πρωτότυπο στις 9 Απριλίου 2010. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ «R6RS Electorate». Scheme Steering Committee. 2007. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Marc Feeley (compilation) (26 Οκτωβρίου 2007). «Implementors' intentions concerning R6RS». Scheme Steering Committee, r6rs-discuss mailing list. Αρχειοθετήθηκε από το πρωτότυπο στις 20 Αυγούστου 2008. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Ed Martin (20 Ιουλίου 2009). «List of Scheme-using schools». Schemers Inc. Αρχειοθετήθηκε από το πρωτότυπο στις 30 Μαρτίου 2009. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ «List of SICP-using schools». MIT Press. 26 Ιανουαρίου 1999. Αρχειοθετήθηκε από το πρωτότυπο στις 15 Ιουνίου 2008. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Eric Grimson (Άνοιξη 2005). «6.001 Structure and Interpretation of Computer Programs». MIT Open Courseware. Αρχειοθετήθηκε από το πρωτότυπο στις 1 Οκτωβρίου 2009. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Alex Vandiver· Ben Vandiver· Nelson Elhage· Zev Benjamin· Mike Phillips· Alejandro Sedeño (Ιανουάριος 2009). «6.184 - Zombies drink caffeinated 6.001». MIT CSAIL. Αρχειοθετήθηκε από το πρωτότυπο στις 28 Αυγούστου 2009. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ CS 2500: Fundamentals of Computer Science I, Northeastern University
- ↑ CS 1101: Introduction to Program Design (A05): course software Αρχειοθετήθηκε 2010-01-24 στο Wayback Machine., Worcester Polytechnic Institute
- ↑ , βλ. What is Scheme used for? στο «scheme-faq-general». Community Scheme Wiki. 21 Μαρτίου 2009. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Robin Cover (25 Φεβρουαρίου 2002). «DSSSL - Document Style Semantics and Specification Language. ISO/IEC 10179:1996». Cover Pages. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ "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. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Todd Graham Lewis· David Zoll· Julian Missig (2002). «GNOME FAQ from Internet Archive». The Gnome Team, gnome.org. Αρχειοθετήθηκε από το πρωτότυπο στις 22 Μαΐου 2000. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ «guile-gnome». Free Software Foundation. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ Laurence Brevard (9 Νοεμβρίου 2006). «Synopsys MAP-inSM Program Update: EDA Interoperability Developers' Forum» (pdf). Synopsis Inc. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
- ↑ 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. Ανακτήθηκε στις 20 Οκτωβρίου 2009
- ↑ Bill Magnuson· Hal Abelson· Mark Friedman (11 Αυγούστου 2009). «Under the Hood of App Inventor for Android». Google Inc, Official Google Research blog. Ανακτήθηκε στις 20 Οκτωβρίου 2009.
Περαιτέρω ανάγνωση
[Επεξεργασία | επεξεργασία κώδικα]- Structure and Interpretation of Computer Programs, κλασικό κείμενο της επιστήμης των υπολογιστών. (Με βίντεο στο YouTube και βασική σελίδα την homepage.) (Αγγλικά)
- Εισαγωγή στη Scheme και την υλοποίησή της (εναλλακτικός σύνδεσμος) (Αγγλικά)
- Christopher T. Haynes (22 Ιουνίου 1999). «The Scheme Programming Language Standardization Experience». (Αγγλικά)
- Guy L. Steele, Jr.· Richard P. Gabriel. «The Evolution of Lisp» (PDF). Αρχειοθετήθηκε από το πρωτότυπο (pdf) στις 12 Οκτωβρίου 2006. Ανακτήθηκε στις 21 Σεπτεμβρίου 2010. (Αγγλικά)
- Gerald Sussman and Guy Steele. SCHEME: An Interpreter for Extended Lambda Calculus AI Memo 349, MIT Artificial Intelligence Laboratory, Cambridge, Μασαχουσέτη, Δεκέμβριος 1975. (Αγγλικά)
Εξωτερικοί σύνδεσμοι
[Επεξεργασία | επεξεργασία κώδικα]Πολυμέσα σχετικά με το θέμα Scheme (programming language) στο Wikimedia Commons
|