Συγχρονες γλωσσες προγραμματισμού

43

description

Oι προπτυχιακοί φοιτητές επιστήμης υπολογιστών και οι μηχανικοί υπολογιστών έχουν κατά κανόνα πρακτικό προσανατολισμό: μελετούν την υπολογιστική επειδή αγαπούν τον προγραμματισμό και έχουν καλές επιδόσεις σε αυτόν. Το βιβλίο απευθύνεται κατά κύριο λόγο σε αυτόν τον πυρήνα σπουδαστών. Το επίπεδο παρουσίασης δεν απαιτεί καμία γνώση αρχιτεκτονικής υπολογιστών, λειτουργικών συστημάτων, τυπικών γλωσσών και θεωρίας αυτομάτων, μαθηματικής λογικής ή επαγωγικών τεχνικών απόδειξης. Το κυρίως ζητούμενο από ένα μάθημα που πραγματεύεται τις έννοιες των γλωσσών προγραμματισμού είναι να βοηθήσει τον φοιτητή να κατανοήσει τις γλώσσες προγραμματισμού σε ένα ασυνήθιστο επίπεδο αφαίρεσης. Για να επιτευχθεί αυτός ο στόχος, το βιβλίο περιλαμβάνει πολλές ασκήσεις και παραδείγματα «πραγματικού» προγραμματισμού, ώστε να ενθαρρύνει τους σπουδαστές των οποίων το ενδιαφέρον για τον προγραμματισμό είναι πρωτίστως πρακτικού χαρακτήρα. Δεν προϋποθέτει υψηλή μαθηματική ωριμότητα εκ μέρους του αναγνώστη. Είναι σχεδιασμένο ώστε να καθοδηγήσει τους σπουδαστές να επεξεργαστούν νοητικά τις αφηρημένες έννοιες των γλωσσών προγραμματισμού, με αφετηρία απλές ασκήσεις προγραμματισμού. Τα κεφάλαια του βιβλίου χωρίζονται σε δύο κατηγορίες: πρακτικού και φιλοσοφικού χαρακτήρα. Τα πρώτα είναι αυτοτελή «αλφαβητάρια» για τρεις γλώσσες προγραμματισμού διαφορετικών οικογενειών: ML, Java και Prolog. Τα φιλοσοφικού χαρακτήρα κεφάλαια παρουσιάζουν τη θεωρητική πλευρά: τις θεμελιώδεις αρχές των γλωσσών προγραμματισμού. Τα κεφάλαια αυτά εναλλάσσονται με τα κεφάλαια πρακτικού χαρακτήρα, σε μια αλληλουχία που διευκολύνει την παρουσίαση των θεωρητικών ζητημάτων, έτσι ώστε η σύνδεσή τους με την προγραμματιστική πρακτική να είναι όσο το δυνατόν εμφανέστερη.

Transcript of Συγχρονες γλωσσες προγραμματισμού

Page 1: Συγχρονες γλωσσες προγραμματισμού
Page 2: Συγχρονες γλωσσες προγραμματισμού

Adam Brooks WebberUniversity of Winsconsin - Milwaukee

ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Μια πρακτική εισαγωγή

Μετάφραση − επιστημονική επιμέλεια: Γεώργιος Φρ. Γεωργακόπουλος

Ιωάννης Παπαδόγγονας E-BOOK

ΠΑΝΕΠΙΣΤΗΜΙΑΚΕΣ ΕΚΔΟΣΕΙΣ ΚΡΗΤΗΣΙδρυτική δωρεά Παγκρητικής Ενώσεως Αμερικής

ΗΡΑΚΛΕΙΟ 2011

Page 3: Συγχρονες γλωσσες προγραμματισμού

ΠΑΝΕΠΙΣΤΗΜΙΑΚΕΣ ΕΚΔΟΣΕΙΣ ΚΡΗΤΗΣΙΔΡΥΜΑ ΤΕΧΝΟΛΟΓΙΑΣ ΚΑΙ ΕΡΕΥΝΑΣ

Hράκλειο Kρήτης, T.Θ. 1385, 711 10. Tηλ.: 2810 391097, Fax: 2810 391085Aθήνα: Mάνης 5, 10681. Tηλ.: 210 3849020-22, Fax: 210 3301583

e-mail: [email protected]

www.cup.gr

ΣΕΙΡΑ: ΠΑΝΕΠΙΣΤΗΜΙΑΚΗ ΒΙΒΛΙΟΘΗΚΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ / ΕΠΙΣΤΗΜΗ ΥΠΟΛΟΓΙΣΤΩΝ

ΔΙΕΥΘΥΝΤΕΣ ΣΕΙΡΑΣ: Γεώργιος Φρ. Γεωργακόπουλος - Ιωάννης Παπαδόγγονας

Τίτλος πρωτοτύπου: Modern Programming Languages. A Practical Introduction © 2003 by Franklin, Beedle & Associates Inc. © για την ελληνική γλώσσα, 2005 ΠΑΝΕΠΙΣΤΗΜΙΑΚΕΣ ΕΚΔΟΣΕΙΣ ΚΡΗΤΗΣ

Μετάφραση - επιστημονική επιμέλεια: Γεώργιος Φρ. Γεωργακόπουλος, Αναπληρωτής Καθηγητής Τμήματος Επιστήμης Υπολογιστών Πανεπιστημίου Κρήτης Ιωάννης Παπαδόγγονας, Δρ Φυσικής, Επιστημονικός επιμελητής ΠΕΚ Επιμέλεια έκδοσης: Ιωάννης Παπαδόγγονας Στοιχειοθεσία - σελιδοποίηση: ΠΑΝΕΠΙΣΤΗΜΙΑΚΕΣ ΕΚΔΟΣΕΙΣ ΚΡΗΤΗΣ Μακέτα εξωφύλλου: Βάσω Αβραμοπούλου

ISBN 978-960-524-282-4

Page 4: Συγχρονες γλωσσες προγραμματισμού

Στον John Galloway McCubbin

1931-2000

Page 5: Συγχρονες γλωσσες προγραμματισμού

Πρόλογος στην ελληνική έκδοση . . . . . . . . . . . . . . . . . . . . . . . . . xviiΠρόλογος . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xixΕυχαριστίες . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xxiii

KΕΦΑΛΑΙΟ 1: Γλώσσες προγραμματισμού . . . . . . . . . . . . . . . . . . . . 1 1.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2. Η εκπληκτική ποικιλία. . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Προστακτικές γλώσσες . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Συναρτησιακές γλώσσες . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Λογικοκεντρικές γλώσσες . . . . . . . . . . . . . . . . . . . . . . . . . 3 Οντοστρεφείς γλώσσες . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3. Οι παράξενες αντιμαχίες . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.4. Η αξιοπερίεργη εξέλιξη . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.5. Οι πολλαπλές διασυνδέσεις. . . . . . . . . . . . . . . . . . . . . . . . 7 1.6. Σύντομο σχόλιο για τις Διεπαφές για Προγραμματισμό Εφαρμογών 9 1.7. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

KΕΦΑΛΑΙΟ 2: Ο ορισμός των συντακτικών κανόνων. . . . . . . . . . . . . . 11 2.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2. Ενδεικτική γραμματική για την αγγλική γλώσσα . . . . . . . . . . . . 11 2.3. Ενδεικτική γραμματική για μια γλώσσα προγραμματισμού . . . . . . 13 2.4. Ορισμός μιας γραμματικής: η μορφή ΒΝ . . . . . . . . . . . . . . . . 14 2.5. Η σχεδίαση μιας γραμματικής . . . . . . . . . . . . . . . . . . . . . . 16 2.6. Η λεκτική και η φραστική δομή μιας γλώσσας . . . . . . . . . . . . . 18 2.7. Άλλες μορφές γραμματικής . . . . . . . . . . . . . . . . . . . . . . . . 20 Μορφή ΒΝ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Μορφή ΕΒΝ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Συντακτικά διαγράμματα . . . . . . . . . . . . . . . . . . . . . . . . . 22 Ασυμφραστικές τυπικές γραμματικές. . . . . . . . . . . . . . . . . . . 23 2.8. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

Περιεχόμενα

Page 6: Συγχρονες γλωσσες προγραμματισμού

viii ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

KΕΦΑΛΑΙΟ 3: Σύνταξη και σημασιολογία: το σημείο συνάντησης . . . . . . 27 3.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.2. Τελεστές. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.3. Προτεραιότητα . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.4. Προσεταιριστικότητα . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.5. Άλλες πολυσημίες . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.6. Στρυφνές γραμματικές . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.7. Συντακτικά δένδρα και η μορφή EBN των γραμματικών . . . . . . . 38 3.8. Αφηρημένα συντακτικά δένδρα . . . . . . . . . . . . . . . . . . . . . 39 3.9. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

KΕΦΑΛΑΙΟ 4: Γλωσσικά συστήματα . . . . . . . . . . . . . . . . . . . . . . . 43 4.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.2. Η τυπική ακολουθία εργασιών . . . . . . . . . . . . . . . . . . . . . . 43 Βελτιστοποίηση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.3. Παραλλαγές της τυπικής ακολουθίας . . . . . . . . . . . . . . . . . . 49 Η απόκρυψη των ενδιάμεσων βημάτων . . . . . . . . . . . . . . . . . 49 Ενιαία περιβάλλοντα ανάπτυξης (ΕΠΑ) . . . . . . . . . . . . . . . . . 50 Διερμηνηνευτές . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Εικονικές μηχανές . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Ύστερη σύνδεση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Σκιαγράφηση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Δυναμική μετάφραση. . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.4. Συναπτικά στάδια . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Γλωσσοσχεδιαστικό στάδιο . . . . . . . . . . . . . . . . . . . . . . . . 57 Υλοποιητικό στάδιο . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Μεταφραστικό στάδιο . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Συνδετικό στάδιο . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Φορτωτικό στάδιο . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Εκτελεστικό στάδιο . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.5. Αποσφαλματωτές . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 4.6. Εκτελεστική υποστήριξη . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.7. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Page 7: Συγχρονες γλωσσες προγραμματισμού

ΠΕΡΙΕΧΟΜΕΝΑ ix

KΕΦΑΛΑΙΟ 5: Πρώτη επαφή με τη γλώσσα ML . . . . . . . . . . . . . . . . . 67 5.1. Eισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 5.2. Πρώτα βήματα με το γλωσσικό σύστημα ML . . . . . . . . . . . . . . 67 5.3. Σταθερές. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 5.4. Τελεστές. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 5.5. Υποθετικές εκφράσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 5.6. Τυπομετατροπή και εφαρμογή συναρτήσεων . . . . . . . . . . . . . . 73 5.7. Ορισμός μεταβλητών . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 5.8. Ρακοσυλλογή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.9. Πλειάδες και κατάλογοι . . . . . . . . . . . . . . . . . . . . . . . . . . 77 5.10. Ορισμοί συναρτήσεων . . . . . . . . . . . . . . . . . . . . . . . . . . 81 5.11. Τύποι και επισημείωση τύπων . . . . . . . . . . . . . . . . . . . . . . 85 5.12. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

KΕΦΑΛΑΙΟ 6: Τύποι . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 6.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 6.2. Μια ζούγκλα από τύπους . . . . . . . . . . . . . . . . . . . . . . . . . 92 Οι τύποι είναι σύνολα . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Πρωταρχικοί και κατασκευασμένοι τύποι . . . . . . . . . . . . . . . . 93 Απαριθμήματα . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Πλειάδες . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Συμβολοσειρές, συστοιχίες και κατάλογοι . . . . . . . . . . . . . . . . 97 Ενώσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Υπότυποι . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Συναρτησιακοί τύποι . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.3. Η χρήση των τύπων . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Επισημείωση τύπων . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Συναγωγή τύπου . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Έλεγχος ορθοτυπίας . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Ζητήματα ισοδυναμίας τύπων . . . . . . . . . . . . . . . . . . . . . . 106 6.4. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

KΕΦΑΛΑΙΟ 7: Δεύτερη επαφή με τη γλώσσα ML . . . . . . . . . . . . .109 7.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .109 7.2. Γνωστά μας μορφότυπα . . . . . . . . . . . . . . . . . . . . . .109 7.3. Άλλα παραδείγματα απλών μορφοτύπων. . . . . . . . . . . . .110 7.4. Σύνθετα μορφότυπα . . . . . . . . . . . . . . . . . . . . . . . .111

Page 8: Συγχρονες γλωσσες προγραμματισμού

x ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

7.5. Σύνοψη των μορφοτύπων ML μέχρι στιγμής . . . . . . . . . . .112 7.6. Εναλλακτικά μορφότυπα για συναρτήσεις . . . . . . . . . . . .113 7.7. Το μορφοτυπικό ύφος γραφής προγραμμάτων . . . . . . . . . .114 7.8. Τοπικοί ορισμοί μεταβλητών. . . . . . . . . . . . . . . . . . . .116 7.9. Ένθετοι ορισμοί συναρτήσεων. . . . . . . . . . . . . . . . . . .120 7.10. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .122 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .122 KΕΦΑΛΑΙΟ 8: Πολυμορφισμός . . . . . . . . . . . . . . . . . . . . . . .125 8.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .125 8.2. Υπερφόρτιση . . . . . . . . . . . . . . . . . . . . . . . . . . . .125 8.3. Μετασκευή παραμέτρων . . . . . . . . . . . . . . . . . . . . . .128 8.4. Παραμετρικός πολυμορφισμός . . . . . . . . . . . . . . . . . .131 8.5. Υποτυπικός πολυμορφισμός . . . . . . . . . . . . . . . . . . . .133 8.6. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .135 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .137 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .139

KΕΦΑΛΑΙΟ 9: Τρίτη επαφή με τη γλώσσα ML . . . . . . . . . . . . . . .141 9.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .141 9.2. Μορφότυπα − η συνέχεια . . . . . . . . . . . . . . . . . . . . .141 9.3. Τιμές συναρτήσεων και ανώνυμες συναρτήσεις . . . . . . . . .143 9.4. Υψηλοτάξιες συναρτήσεις και επαλληλία παραμέτρων . . . . .146 9.5. Προκαθορισμένες υψηλοτάξιες συναρτήσεις . . . . . . . . . . .148 Η απεικονιστική συνάρτηση map . . . . . . . . . . . . . . . . . . . . 148 Η δ-σωρευτική συνάρτηση foldr . . . . . . . . . . . . . . . . . . . 149 Η α-σωρευτική συνάρτηση foldl . . . . . . . . . . . . . . . . . . . 152 9.6. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .153 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .153

KΕΦΑΛΑΙΟ 10: Εμβέλεια. . . . . . . . . . . . . . . . . . . . . . . . . . .157 10.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157 10.2. Ορισμοί και εμβέλεια. . . . . . . . . . . . . . . . . . . . . . . .158 10.3. Εμβελειοθέτηση μέσω παραγράφων . . . . . . . . . . . . . . .160 10.4. Εμβελειοθέτηση με επώνυμους ονοματοχώρους . . . . . . . . .163 10.5. Εμβελειοθέτηση με πρωταρχικούς ονοματοχώρους . . . . . . .167 10.6. Δυναμική εμβελειοθέτηση . . . . . . . . . . . . . . . . . . . . .169 10.7. Λίγα σχόλια για την τμηματική μετάφραση . . . . . . . . . . .171 10.8. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .172 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .173 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

Page 9: Συγχρονες γλωσσες προγραμματισμού

ΠΕΡΙΕΧΟΜΕΝΑ xi

KΕΦΑΛΑΙΟ 11: Τέταρτη επαφή με τη γλώσσα ML . . . . . . . . . . . .177 11.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .177 11.2. Απαριθμήματα . . . . . . . . . . . . . . . . . . . . . . . . . . .177 11.3. Τιμοκατασκευαστές με παραμέτρους . . . . . . . . . . . . . . .179 11.4. Τυποκατασκευαστές με παραμέτρους . . . . . . . . . . . . . . .181 11.5. Αναδρομικοί τυποκατασκευαστές . . . . . . . . . . . . . . . . .183 11.6. Ανακεφαλαίωση και αποχαιρετισμός στην ML . . . . . . . . . .188 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .190 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .191

KΕΦΑΛΑΙΟ 12: Οι θέσεις μνήμης για τις μεταβλητές . . . . . . . . . .193 12.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .193 12.2. Ενεργοειδικές μεταβλητές . . . . . . . . . . . . . . . . . . . . .193 Άλλα είδη μεταβλητών . . . . . . . . . . . . . . . . . . . . . . .195 12.3. Δελτία ενεργοποίησης . . . . . . . . . . . . . . . . . . . . . . .196 12.4. Στατική δέσμευση των δελτίων ενεργοποίησης . . . . . . . . .197 12.5. Στοίβες και δυναμική δέσμευση των δελτίων ενεργοποίησης . .198 12.6. Χειρισμός ένθετων ορισμών συναρτήσεων . . . . . . . . . . . .205 12.7. Οι συναρτήσεις ως παράμετροι . . . . . . . . . . . . . . . . . .210 12.8. Μακρόβιες συναρτήσεις . . . . . . . . . . . . . . . . . . . . . .213 12.9. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .215 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .216

KΕΦΑΛΑΙΟ 13: Πρώτη επαφή με τη γλώσσα Java . . . . . . . . . . . . .219 13.1. Eισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .219 13.2. Με τις οντότητες κατά νου . . . . . . . . . . . . . . . . . . . .220 13.3. Απλές εκφράσεις και εντολές . . . . . . . . . . . . . . . . . . .222 Σταθερές και τύποι δεδομένων . . . . . . . . . . . . . . . . . . . . . 222 Τελεστές για πράξεις επί ακεραίων . . . . . . . . . . . . . . . . . . . 224 Τελεστές για πράξεις επί πραγματικών . . . . . . . . . . . . . . . . . 224 Συναρμογή συμβολοσειρών . . . . . . . . . . . . . . . . . . . . . . . 225 Συγκριτικοί τελεστές . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Λογικοί τελεστές . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Παρενεργικοί τελεστές . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Κλήσεις μεθόδων . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Οντοπαραγωγικές εκφράσεις . . . . . . . . . . . . . . . . . . . . . . 232

Προσεταιριστικότητα, προτεραιότητες, μετασκευές, κ .λπ . . . . . . . 233 Απλές εντολές. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Σύνθετες εντολές . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Δηλωτικές εντολές . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

Page 10: Συγχρονες γλωσσες προγραμματισμού

xii ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Η υποθετική εντολή if . . . . . . . . . . . . . . . . . . . . . . . . . 235 Η επαναληπτική εντολή while . . . . . . . . . . . . . . . . . . . . 236 Η επιστροφική εντολή return . . . . . . . . . . . . . . . . . . . . . 237 13.4. Ορισμοί κλάσεων. . . . . . . . . . . . . . . . . . . . . . . . . .238 13.5. Παραπομπές και δείκτες . . . . . . . . . . . . . . . . . . . . . .243 13.6. Πρώτη επαφή με ένα γλωσσικό σύστημα Java . . . . . . . . . .245 13.7. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .248 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .248 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .251

KΕΦΑΛΑΙΟ 14: Διαχείριση μνήμης . . . . . . . . . . . . . . . . . . . . .253 14.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .253 14.2. Ένα μοντέλο μνήμης με χρήση συστοιχιών της Java . . . . . . .253 14.3. Στοίβες . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .256 14.4. Σωροί . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .260 Ο μηχανισμός της «πρώτης επαρκούς» περιοχής . . . . . . . . . . . 261 Συγκόλληση συνεχόμενων αδέσμευτων περιοχών . . . . . . . . . . . 267 Πρόχειροι κατάλογοι και ύστερη συγκόλληση . . . . . . . . . . . . . 269 Κατακερματισμός μνήμης . . . . . . . . . . . . . . . . . . . . . . . . 271 Άλλες τεχνικές διαχείρισης του μνημοσωρού . . . . . . . . . . . . . 272 14.5. Τρέχουσες σωροπαραπομπές . . . . . . . . . . . . . . . . . . .274 Εντοπισμός των τρεχουσών σωροπαραπομπών . . . . . . . . . . 274 Σύμπτυξη σωρού . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Ρακοσυλλογή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 14.6. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .284 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .284 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .287 KΕΦΑΛΑΙΟ 15: Δεύτερη επαφή με τη γλώσσα Java . . . . . . . . . . . .289 15.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .289 15.2. Η υλοποίηση διεπαφών . . . . . . . . . . . . . . . . . . . . . .289 15.3. Επέκταση κλάσεων . . . . . . . . . . . . . . . . . . . . . . . .295 15.4. Επέκταση και υλοποίηση. . . . . . . . . . . . . . . . . . . . . .301 15.5. Πολλαπλή κληρονόμηση και υποκατάστατά της . . . . . . . . .302 15.6. Αρχέτυπα και υποκατάστατά τους . . . . . . . . . . . . . . . .304 15.7. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .308 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .308

Page 11: Συγχρονες γλωσσες προγραμματισμού

ΠΕΡΙΕΧΟΜΕΝΑ xiii

KΕΦΑΛΑΙΟ 16: Οντοστρέφεια . . . . . . . . . . . . . . . . . . . . . . .317 16.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .317 16.2. Οντοστρεφής προγραμματισμός . . . . . . . . . . . . . . . . .318 Οντοστρεφής ML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Μη οντοστρεφής Java . . . . . . . . . . . . . . . . . . . . . . . . . . 323 Σύνοψη . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 16.3. Οντοστρεφείς γλώσσες - απάνθισμα χαρακτηριστικών. . . . .326 Κλάσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 Πρωτότυπα . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327

Κληρονόμηση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Ενθυλάκωση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 Πολυμορφισμός . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331

16.4. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .333 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .334 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .337

KΕΦΑΛΑΙΟ 17: Τρίτη επαφή με τη γλώσσα Java . . . . . . . . . . . . .339 17.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .339 17.2. Εκπέμψιμες οντότητες . . . . . . . . . . . . . . . . . . . . . . .340 17.3. Παραλαβή εξαιρέσεων . . . . . . . . . . . . . . . . . . . . . . .342 17.4. Εκπομπή εξαιρέσεων . . . . . . . . . . . . . . . . . . . . . . . .348 17.5. Ελεγκτέες εξαιρέσεις . . . . . . . . . . . . . . . . . . . . . . . .351 17.6. Διαχείριση σφαλμάτων. . . . . . . . . . . . . . . . . . . . . . .354 Απλή δήλωση των προϋποθέσεων. . . . . . . . . . . . . . . . . . . . 356 Εξαντλητικοί ορισμοί . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 Καταστροφικά σφάλματα . . . . . . . . . . . . . . . . . . . . . . . . 358 Σήμανση των σφαλμάτων . . . . . . . . . . . . . . . . . . . . . . . . 359 Εκπομπή εξαιρέσεων . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 17.7. Και «τελικά» . . . . . . . . . . . . . . . . . . . . . . . . . . . .365 17.8. Ανακεφαλαίωση και αποχαιρετισμός στην Java . . . . . . . . .367 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .368 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .379

KΕΦΑΛΑΙΟ 18: Παράμετροι . . . . . . . . . . . . . . . . . . . . . . . . .381 18.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .381 18.2. Αντιστοιχία . . . . . . . . . . . . . . . . . . . . . . . . . . . . .382 18.3. Τιμοδοτική διαβίβαση . . . . . . . . . . . . . . . . . . . . . . .383 18.4. Τιμοληπτική διαβίβαση . . . . . . . . . . . . . . . . . . . . . .386 18.5. Δοσοληπτική διαβίβαση . . . . . . . . . . . . . . . . . . . . . .389

Page 12: Συγχρονες γλωσσες προγραμματισμού

xiv ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

18.6. Παραπεμπτική διαβίβαση . . . . . . . . . . . . . . . . . . . . .391 18.7. Διαβίβαση μέσω ανάπτυξης μακροεντολής . . . . . . . . . . . .396 18.8. Ονομαστική διαβίβαση . . . . . . . . . . . . . . . . . . . . . .399 18.9. Οικονομική (ονομαστική) διαβίβαση . . . . . . . . . . . . . . .401 18.10. Ζητήματα προδιαγραφών . . . . . . . . . . . . . . . . . . . . .403 18.11. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .404 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .405

KΕΦΑΛΑΙΟ 19: Πρώτη επαφή με τη γλώσσα Prolog . . . . . . . . . . .407 19.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .407 19.2. Οι δομικοί λίθοι: οι όροι της Prolog. . . . . . . . . . . . . . . .408 19.3. Πρώτα βήματα με ένα γλωσσικό σύστημα Prolog . . . . . . . .410 19.4. Κανόνες . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .415 19.5. Οι δύο όψεις της Prolog . . . . . . . . . . . . . . . . . . . . . .418 19.6. Ένα μικρό σχόλιο για την ερμηνεία των όρων . . . . . . . . . .420 19.7. Τελεστές . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .421 19.8. Κατάλογοι . . . . . . . . . . . . . . . . . . . . . . . . . . . . .423 Ειδικός συμβολισμός σχετικά με τους καταλόγους . . . . . . . . . . 423 Το προσαρτησιακό κατηγόρημα append και άλλα ευέλικτα κατηγορήματα . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 Το αντιστρεπτικό κατηγόρημα reverse και άλλα μη ευέλικτα κατηγορήματα . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428 Η ανώνυμη μεταβλητή . . . . . . . . . . . . . . . . . . . . . . . . . . 430 19.9. Αρνήσεις και αποτυχίες . . . . . . . . . . . . . . . . . . . . . .431 19.10. Το είδος των εργασιών για τις οποίες προσφέρεται η Prolog . .433 19.11. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .436 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .436 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .439

KΕΦΑΛΑΙΟ 20: Δεύτερη επαφή με τη γλώσσα Prolog . . . . . . . . . .441 20.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .441 20.2. Ενοποίηση . . . . . . . . . . . . . . . . . . . . . . . . . . . . .441 Ο έλεγχος εμφάνισης . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 20.3. Μια διαδικαστική θεώρηση . . . . . . . . . . . . . . . . . . . .445 Οπισθοχώρηση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 Αντικατάσταση . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447 20.4. Μια υλοποιητική θεώρηση . . . . . . . . . . . . . . . . . . . . .449 Το αναλυτικό βήμα . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449 Ο διερμηνευτής της Prolog. . . . . . . . . . . . . . . . . . . . . . . . 450 Η συγκέντρωση των αντικαταστάσεων. . . . . . . . . . . . . . . . . 452

Page 13: Συγχρονες γλωσσες προγραμματισμού

ΠΕΡΙΕΧΟΜΕΝΑ xv

20.5. Μια αφηρημένη θεώρηση - τα αποδεικτικά δένδρα . . . . . . .454 Ο ορισμός των αποδεικτικών δένδρων . . . . . . . . . . . . . . . . . 454 Άπειρα αποδεικτικά δένδρα . . . . . . . . . . . . . . . . . . . . . . . 456 Μετονομασίες μεταβλητών . . . . . . . . . . . . . . . . . . . . . . . 457 20.6. Η πιο ανάλαφρη όψη της Prolog . . . . . . . . . . . . . . . . .460 Τα άτομα ως συμβολοσειρές . . . . . . . . . . . . . . . . . . . . . . . 461 Αναγραφή και ανάγνωση : write και read . . . . . . . . . . . . . . 461

Βεβαίωση και ανάκληση: assert και retract . . . . . . . . . . . . 462 Ένα παιγνίδι περιπέτειας . . . . . . . . . . . . . . . . . . . . . . . . . 464 20.7. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .471 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .472

KΕΦΑΛΑΙΟ 21: Κοστολόγηση . . . . . . . . . . . . . . . . . . . . . . .475 21.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .475 21.2. Κοστολόγηση πράξεων σε καταλόγους . . . . . . . . . . . . . .476 21.3. Κοστολόγηση της κλήσης συναρτήσεων . . . . . . . . . . . . .481 21.4. Κοστολόγηση της αναζήτησης στην Prolog . . . . . . . . . . .488 21.5. Κοστολόγηση πράξεων σε συστοιχίες. . . . . . . . . . . . . . .490 21.6. Εφήμερες αρχές κοστολόγησης . . . . . . . . . . . . . . . . . .496 21.7. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .498 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .499

KΕΦΑΛΑΙΟ 22: Τρίτη επαφή με τη γλώσσα Prolog . . . . . . . . . . .503 22.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .503 22.2. Αριθμητικοί υπολογισμοί . . . . . . . . . . . . . . . . . . . . .503 Αριθμητική αποτίμηση . . . . . . . . . . . . . . . . . . . . . . . . . . 504 Αριθμητικές συγκρίσεις . . . . . . . . . . . . . . . . . . . . . . . . . 506 Παραδείγματα . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 22.3. Διερεύνηση προβληματοχώρου . . . . . . . . . . . . . . . . . .510 Το πρόβλημα του σακιδίου . . . . . . . . . . . . . . . . . . . . . . . . 510 Το πρόβλημα των οκτώ βασιλισσών. . . . . . . . . . . . . . . . . . . 516 22.4. Ανακεφαλαίωση και αποχαιρετισμός στην Prolog . . . . . . . .522 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .523 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .524

KΕΦΑΛΑΙΟ 23: Τυπική σημασιολογία . . . . . . . . . . . . . . . . . . .527 23.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .527 23.2. Γλώσσα Micro-1 . . . . . . . . . . . . . . . . . . . . . . . . . .527 Ο διερμηνευτής . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529 Μια φυσική σημασιολογία . . . . . . . . . . . . . . . . . . . . . . . . 532

Page 14: Συγχρονες γλωσσες προγραμματισμού

xvi ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

23.3. Γλώσσα Micro-2: η προσθήκη μεταβλητών . . . . . . . . . . . .533 Ο διερμηνευτής . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534 Μια φυσική σημασιολογία . . . . . . . . . . . . . . . . . . . . . . . . 536 Περί σφαλμάτων . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 23.4. Γλώσσα Micro-3: η προσθήκη συναρτήσεων . . . . . . . . . . .538 Ένας διερμηνευτής . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 Μια φυσική σημασιολογία . . . . . . . . . . . . . . . . . . . . . . . . 543 Περί σφαλμάτων . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543 Περί της σειράς αποτίμησης . . . . . . . . . . . . . . . . . . . . . . . 544 23.5. Άλλα είδη τυπικής σημασιολογίας . . . . . . . . . . . . . . . .546 Εκτελεστική σημασιολογία . . . . . . . . . . . . . . . . . . . . . . . 546 Αξιωματική σημασιολογία . . . . . . . . . . . . . . . . . . . . . . . . 547 Υποδηλωτική σημασιολογία . . . . . . . . . . . . . . . . . . . . . . . 549 23.6. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .550 Ασκήσεις . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .551 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .554

KΕΦΑΛΑΙΟ 24: Η ιστορία των γλωσσών προγραμματισμού . . . . . . .555 24.1. Εισαγωγή . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .555 24.2. Η προϊστορία του προγραμματισμού . . . . . . . . . . . . . . .555 Η ιστορία των βαβυλώνιων προγραμματιστών . . . . . . . . . . . . 555 Η ιστορία του Μοχάμεντ Αλ-Χουάριζμι . . . . . . . . . . . . . . . . 557 Η ιστορία της Augusta Ada, κόμισσας του Lovelace . . . . . . . . . . 557 24.3. Πρώιμες γλώσσες προγραμματισμού . . . . . . . . . . . . . . .559 Η ιστορία της Plankalkül. . . . . . . . . . . . . . . . . . . . . . . . . 559 Η ιστορία της Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . 561 Η ιστορία της Lisp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565 Η ιστορία της Algol . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568 Η ιστορία της Smalltalk . . . . . . . . . . . . . . . . . . . . . . . . . 572 24.4. Οι γλώσσες που εξετάσαμε σε αυτό το βιβλίο . . . . . . . . . .575 Η ιστορία της Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 Η ιστορία της ML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577

Η ιστορία της Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578 24.5. Ανακεφαλαίωση . . . . . . . . . . . . . . . . . . . . . . . . . .581 Βιβλιογραφία . . . . . . . . . . . . . . . . . . . . . . . . . . . .582

Επίλογος . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .585Ευρετήριο . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .587Γλωσσάριο . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .601

Page 15: Συγχρονες γλωσσες προγραμματισμού

Πρόλογος στην ελληνική έκδοση

Οι Πανεπιστημιακές Εκδόσεις Κρήτης έχουν την χαρά να παρουσιάσουν το βι-βλίο Σύγχρονες γλώσσες προγραμματισμού, του Adam Brooks Webber. Το συγκε-κριμένο σύγγραμμα επιλέχθηκε διότι είναι από τα ελάχιστα αυτού του είδους στη διεθνή βιβλιογραφία. Τα πιο αξιοσημείωτα χαρακτηριστικά του είναι τα εξής:

α) Ο τρόπος προσέγγισης. Ο συγγραφέας δεν πραγματεύεται, όπως γίνεται συνήθως, απλά και μόνο κάποια ή κάποιες συγκεκριμένες γλώσσες προγραμ-ματισμού, αλλά το ίδιο το φαινόμενο των γλωσσών προγραμματισμού: Πώς και γιατί έχουν αναπτυχθεί γλώσσες προγραμματισμού με διαφορετικές μορφές; Τι εκφραστική αξία έχουν αυτές οι γλώσσες; Ποιες είναι οι κυριότερες τεχνοτρο πίες προγραμματισμού (λ.χ. προστακτική, οντοστρεφής, συναρτησιακή, λογικοκε-ντρική, κ.λπ.), και πώς χρησιμοποιούνται;

β) Ο βαθμός εμβάθυνσης. Ο συγγραφέας δεν μένει στα «φαινόμενα», αλλά διεισδύει στο παρασκήνιο των γλωσσών, δηλαδή στα καθήκοντα των γλωσσικών συστημάτων: Πώς είναι δυνατή η υλοποίηση γλωσσών με μύρια διαφορετικά χαρακτηριστικά; Πώς δομούνται τα γλωσσικά συστήματα που κάνουν εφικτή τη μαγεία του προγραμματισμού σε οποιoδήποτε προγραμματιστικό ύφος; Τι προ-βλήματα καλούνται να λύσουν και πώς το επιτυγχάνουν;

γ) Η μέθοδος διδασκαλίας. Ο συγγραφέας εναλλάσσει (στη ροή των κεφα-λαίων) την αφ’ υψηλού θεώρηση με την εισαγωγική και πρακτική διδασκαλία τριών γλωσσών προγραμματισμού (ML, Java, Prolog), που αντιστοιχούν σε τρία θεμελιώδη είδη προγραμματισμού: τον οντοστρεφή, τον συναρτησιακό και τον λογικοκεντρικό προγραμματισμό. Η παρουσίαση παραμένει απλή, εισαγωγική, και αποτελεσματικά διδακτική με ευχάριστο τρόπο.

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

Page 16: Συγχρονες γλωσσες προγραμματισμού

xviii ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

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

Τόσο η ορολογία όσο και η φύση του θέματος προκαλούν εύλογα πολλές με-ταφραστικές δυσκολίες (αφού σχεδόν όλες οι γλώσσες προγραμματισμού γρά-φονται στην αγγλική γλώσσα). Σε κάποιες περιπτώσεις κρίναμε σκόπιμο να πα-ρεμβάλουμε σχόλια στον κώδικα, τα οποία ξεκινούν με τη διπλή πλάγια κάθετο, //. Σε άλλα σημεία προσθέσαμε υποσημειώσεις με αστερίσκο για τη μετάφραση κάποιων από τα μηνύματα των γλωσσικών συστημάτων, ενώ σε λίγες περιπτώσεις τροποποιήσαμε ορισμένες ονομασίες μεταβλητών ώστε να είναι πιο κατανοη τές από τον Έλληνα αναγνώστη. Εν γένει, επιμεληθήκαμε αυτό το βιβλίο και την ορολογία του γνωστικού αντικειμένου με ιδιαίτερη φροντίδα, ώστε να έχουμε μια γνήσια ελληνική μετάφραση, και όχι ένα κουραστικό μίγμα από ελληνικούς και αγγλικούς όρους. Για όσες περιπτώσεις δεν το κατορθώσαμε, ελπίζουμε στην κατανόηση του αναγνώστη.

Τέλος, θα θέλαμε να ευχαριστήσουμε την κ. Διονυσία Δασκάλου, γενική επι-μελήτρια των ΠΕΚ, για τη συμβολή της σε διάφορα στάδια της παραγωγής του βιβλίου.

Γιώργος Φρ. ΓεωργακόπουλοςΙωάννης Παπαδόγγονας

Page 17: Συγχρονες γλωσσες προγραμματισμού

Πρόλογος

Το βιβλίο αυτό έχει τον χαρακτήρα διδακτικού εγχειριδίου για το εισαγωγικό γε νικό μάθημα περί γλωσσών προγραμματισμού το οποίο διδάσκεται σε προπτυ-χιακούς φοιτητές επιστήμης υπολογιστών και μηχανολογίας υπολογιστών. Προ-σφέρεται για ένα μάθημα που εισάγει τις γενικές έννοιες των ποικίλων γλωσσών προγραμματισμού, και απευθύνεται σε φοιτητές που έχουν ήδη αρκετή ευχέρεια στον βασικό προγραμματισμό σε μία τουλάχιστον γλώσσα. Πραγματεύεται όλα τα βασικά θέματα των γλωσσών προγραμματισμού τα οποία προτείνονται στην έκθεση της ACM* σχετικά με τα προγράμματα σπουδών στην υπολογιστική (προ σχέδιο Steelman), και εισάγει τα πιο κεντρικά από αυτά τα θέματα με αρκε-τές λεπτομέρειες.

Η ύλη του βιβλίου είναι διαρθρωμένη έτσι ώστε να διεγείρει το ενδιαφέρον του σύγχρονου φοιτητή. Η συνήθης προσέγγιση σε τέτοιου είδους βιβλία είναι να παρουσιάζεται η ιστορία των σημαντικότερων γλωσσών προγραμματισμού, και κατόπιν να μελετούνται λεπτομερώς οι γλώσσες αυτές μέσω μιας διδακτικής ακολουθίας που καθοδηγείται από κάποιες έννοιες ή κάποια παραδείγματα. Οι περισσότεροι φοιτητές της επιστήμης υπολογιστών, όμως, δεν είναι σε θέση να εκτιμήσουν πλήρως τις εξελικτικές λεπτομέρειες, την αφαίρεση χωρίς συγκεκρι-μένο στόχο, και την κατάταξη σε κατηγορίες. Οι προπτυχιακοί φοιτητές επιστή-μης και μηχανολογίας υπολογιστών έχουν κατά κανόνα πρακτικό προσανατο-λισμό: μελετούν την υπολογιστική επειδή τους αρέσει ο προγραμματισμός και είναι καλοί σε αυτόν. Άλλοι φοιτητές μελετούν την υπολογιστική επειδή τους αρέσει η θεωρητική επιστήμη υπολογιστών και είναι καλοί σε αυτήν. Το ζητούμε-νο από ένα μάθημα για τις βασικές έννοιες των γλωσσών προγραμματισμού είναι να βοηθήσει όλους τους φοιτητές να κατανοήσουν τις γλώσσες προγραμματι-σμού σε ένα ασυνήθιστο επίπεδο αφαίρεσης. Προκειμένου να επιτευχθεί αυτός ο στόχος, το βιβλίο περιλαμβάνει αρκετές ασκήσεις προγραμματισμού και παρα-δείγματα πρακτικής φύσεως, ώστε να συντηρήσει το ενδιαφέρον των φοιτητών με πιο πρακτικό προσανατολισμό, χωρίς να προϋποθέτει από τον αναγνώστη

* Association for Computing Machinery: Ένωση για τον Υπολογιστικό Εξοπλισμό

Page 18: Συγχρονες γλωσσες προγραμματισμού

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

Τα κεφάλαια του βιβλίου χωρίζονται σε δύο κατηγορίες: πρακτικού και φιλο-σοφικού χαρακτήρα. Τα πρώτα είναι αυτοτελή «αλφαβητάρια» για τρεις γλώσ-σες προγραμματισμού. Σε αυτά αναπτύσσεται ένα επίπεδο δεξιότητας που θα επιτρέψει στον φοιτητή να διεκπεραιώνει απλές ασκήσεις προγραμματισμού. Η ενασχόληση με τον προγραμματισμό σε διάφορες οικογένειες γλωσσών είναι ιδιαίτερα σημαντική για τον φοιτητή. Το βιβλίο περιλαμβάνει εισαγωγές στον προγραμματισμό για τρεις γλώσσες –την ML, την Java και την Prolog– από τις οποίες οι δύο τουλάχιστον θα είναι άγνωστες σε όλους σχεδόν τους φοιτητές αυ-τού του επιπέδου. (Υπάρχουν εξαιρετικές δωρεάν υλοποιήσεις όλων αυτών των γλωσσών για διάφορα υπολογιστικά πλαίσια, μεταξύ των οποίων τα Windows, το Unix και το λειτουργικό σύστημα Macintosh. Στον Ιστότοπο αυτού του βι-βλίου, http://www.webber-labs.com/mpl.html, υπάρχουν οδηγίες για το πώς μπο ρεί κανείς να προμηθευτεί μια τέτοια υλοποίηση.) Τα κεφάλαια πρακτικού χαρακτήρα περιλαμβάνουν μια σύντομη εισαγωγή στις ιδιαιτερότητες της κάθε γλώσσας. Δεν καλύπτουν όμως τις Διεπαφές για Προγραμματισμό Εφαρμογών. Ως εκ τούτου, θα δώσουν μεν στον φοιτητή τη δυνατότητα να επιλύει ασκήσεις προγραμματισμού, αλλά όχι και να αναπτύσσει ολοκληρωμένες εφαρμογές με-γάλης κλίμακας.

Στα κεφάλαια φιλοσοφικού χαρακτήρα παρουσιάζεται η θεωρητική πλευρά: οι υποκείμενες αρχές των γλωσσών προγραμματισμού. Τα κεφάλαια αυτά εναλ-λάσσονται με τα κεφάλαια πρακτικού χαρακτήρα, σε μια αλληλουχία που επι-τρέπει την αποσαφήνιση των εννοιών μέσω παραδειγμάτων από την πρόσφατα διδαχθείσα γλώσσα, και διευκολύνει την παρουσίαση των θεωρητικών ζητημά-των στην κατάλληλη χρονική συγκυρία ώστε η σύνδεσή τους με την προγραμμα-τιστική πρακτική να είναι όσο το δυνατόν εμφανέστερη. Παραδείγματος χάριν, το Κεφάλαιο 23 πραγματεύεται την τυπική σημασιολογία ξεκινώντας από κάποιους απλούς διερμηνευτές γραμμένους σε Prolog. Οι διερμηνευτές αυτοί οδηγούν με φυσιολογικό τρόπο σε ορισμούς γλωσσών μέσω μακροβηματικής εκτελεστικής σημασιολογίας. Αυτός είναι και ο λόγος που η τυπική σημασιολογία εμφανίζεται τόσο αργά σε αυτό το βιβλίο: μόνο αφότου έχει ολοκληρωθεί η παρουσίαση της Prolog, είναι σε θέση οι φοιτητές να μεταβούν από τις ασκήσεις Prolog σε αυτό το συναφές, αφηρημένο ζήτημα.

Το βιβλίο είναι γραμμένο σε εισαγωγικό επίπεδο. Έχει ως στόχο να είναι κατα-νοητό και ενδιαφέρον για την πλειονότητα των φοιτητών που έχουν ολοκληρώ-σει μια βασική σειρά μαθημάτων ΕΥ1/ΕΥ2 σε οποιαδήποτε γλώσσα. Ένα συνηθι-σμένο μειονέκτημα στα υπάρχοντα βιβλία για αυτό το γνωστικό αντικείμενο εί-

xx ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Page 19: Συγχρονες γλωσσες προγραμματισμού

ΠΡΟΛΟΓΟΣ xxi

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

Λόγω της αφηγηματικής του δομής και της γραμμικής διδακτικής του συ-γκρότησης, το βιβλίο μπορεί να χρησιμοποιηθεί εύκολα για διδασκαλία εάν ακο-λουθηθεί η υπάρχουσα σειρά παρουσίασης της ύλης, εφ’ όσον βέβαια υπάρχουν τα χρονικά περιθώρια για κάτι τέτοιο. Εάν οι φοιτητές γνωρίζουν ήδη κάποια από τις γλώσσες (το πιθανότερο την Java), κάποια από τα διδακτικά κεφάλαια είναι δυνατόν να παραλειφθούν ή να παρουσιαστούν επί τροχάδην, ώστε να μεί-νει χρόνος για λεπτομερέστερη κάλυψη άλλων, ή για την παρουσίαση επιπλέον ύλης. Για την περίπτωση που είναι απαραίτητο να παραλειφθούν και άλλα κεφά-λαια, παραθέτουμε αμέσως παρακάτω χονδρικά τις πιο σημαντικές αλληλεξαρ-τήσεις μεταξύ των κεφαλαίων:

Κεφάλαιο Κεφάλαια στα οποία βασίζεται

1: Γλώσσες προγραμματισμού 2: Ο ορισμός των συντακτικών κανόνων 3: Σύνταξη και σημασιολογία: το σημείο συνάντησης 24: Γλωσσικά συστήματα 5: Πρώτη επαφή με τη γλώσσα ML 2, 36: Τύποι 47: Δεύτερη επαφή με τη γλώσσα ML 2, 3, 58: Πολυμορφισμός 4, 69: Τρίτη επαφή με τη γλώσσα ML 2, 3, 5, 710: Εμβέλεια 411: Τέταρτη επαφή με τη γλώσσα ML 2, 3, 5, 7, 8, 9

Page 20: Συγχρονες γλωσσες προγραμματισμού

xxii ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Κεφάλαιο Κεφάλαια στα οποία βασίζεται

12: Οι θέσεις μνήμης για τις μεταβλητές 4, 5, 7, 913: Πρώτη επαφή με τη γλώσσα Java 2, 314: Διαχείριση μνήμης 2, 3, 1315: Δεύτερη επαφή με τη γλώσσα Java 2, 3, 1316: Οντοστρέφεια 2, 3, 5, 7, 9, 13, 1517: Τρίτη επαφή με τη γλώσσα Java 2, 3, 13, 1518: Παράμετροι 2, 3, 1319: Πρώτη επαφή με τη γλώσσα Prolog 2, 320: Δεύτερη επαφή με τη γλώσσα Prolog 2, 3, 1921: Κοστολόγηση 2, 3, 4, 5, 13, 19, 2022: Τρίτη επαφή με τη γλώσσα Prolog 2, 3, 19, 2023: Τυπική σημασιολογία 2, 3, 4, 5, 7, 9, 10, 1224: Η ιστορία των γλωσσών προγραμματισμού Διάφορα

Ειδικότερα, τα Κεφάλαια 11, 14, 21 και 22 μπορούν να παραλειφθούν χωρίς ιδιαί-τερη βλάβη των υπολοίπων. Εάν ο χρόνος πιέζει προς το τέλος του εξαμήνου, θα ήταν καλύτερα να παραλειφθούν τα Κεφάλαια 21 και 22 παρά τα Κεφάλαια 23 ή 24. Στο Κεφάλαιο 23 επανεξετάζονται και διευκρινίζονται πολλές σημαντι-κές έννοιες από τα προηγούμενα κεφάλαια. Το Κεφάλαιο 24 είναι τελευταίο όχι επειδή η ιστορία των γλωσσών προγραμματισμού είναι ασήμαντο ζήτημα, αλλά επειδή γίνεται πιο ενδιαφέρον όταν οι φοιτητές κατανοούν κάποιες από τις έν-νοιες των οποίων η ιστορική εξέλιξη παρουσιάζεται.

Η διεύθυνση του Ιστοτόπου αυτού του βιβλίου είναι http://www.webber-labs.com/mpl.html. Εκεί μπορεί κανείς να βρει, μεταξύ άλλων, ένα πλήρες σύνολο από διαφάνειες για κάθε κεφάλαιο, χρήσιμους συνδέσμους για καταφόρτωση και εγκατάσταση δωρεάν γλωσσικών συστημάτων, και όλα τα μακροσκελή τμήματα κώδικα που χρησιμοποιούνται ως παραδείγματα στο κείμενο και τις ασκήσεις. Υπάρχουν επίσης οδηγίες για να επικοινωνήσει κανείς με τον συγγραφέα προ-κειμένου να αναφέρει ελαττώματα, και για να αποκτήσει πρόσβαση σε επιπλέον διδακτικό υλικό αποκλειστικά για τους διδάσκοντες.

Page 21: Συγχρονες γλωσσες προγραμματισμού

Ευχαριστίες

Η οικογένειά μου με βοήθησε σημαντικά σε όλη τη διάρκεια της συγγραφής αυτού του βιβλίου, ιδιαίτερα η σύζυγός μου Kelly και τα παιδιά μου Fern και Fox. Θα αναφέρω ένα μόνο παράδειγμα: ο μικρός μου Fox, μόλις δύο ετών, μια μέρα καθώς έγραφα άνοιξε την πόρτα του γραφείου μου, είπε «αγκαλιά», με αγκάλιασε και κατόπιν έφυγε, κλείνοντας την πόρτα πίσω του. Όλοι τους φάνηκαν πραγματικά πολύ γενναιόδωροι, αφήνοντάς μου αρκετό χρόνο για τις ανάγκες της συγγραφής του βιβλίου. Σας ευχαριστώ αγαπημένοι μου.

Στις αρχές της δεκαετίας του 1980, συνεργάστηκα με μια εκπληκτική ομάδα προγραμματιστών: τους φοιτητές και το διδακτικό προσωπικό του Kiewit Computation Center του Dartmouth College. Η ιδιόμορφη πρακτική της συγγραφής συστημικού λογισμικού από φοιτητές, η οποία ήταν καθι-ερωμένη στο Dartmouth, υπήρξε ιδιαίτερα επωφελής για μένα. Μέντοράς μου στο Kiewit ήταν ο Philip D. L. Koch, δημιουργός μιας υπέροχης συλλο-γής προγραμμάτων η οποία περιλάμβανε ένα λειτουργικό σύστημα κεντρι-κού υπολογιστή και έναν εξαιρετικό μεταφραστή της PL/I. Αυτό υπήρξε η απαρχή του ενδιαφέροντός μου για τις γλώσσες προγραμματισμού.

Είμαι ευγνώμων στους φοιτητές μου στο Πανεπιστήμιο του Wisconsin – Milwaukee και στο Πανεπιστήμιο του Western Illinois, οι οποίοι άντεξαν τους καλοπροαίρετους πειραματισμούς μου και με βοήθησαν να αναπτύξω, στη διάρκεια κάποιων ετών, τη δομή του μαθήματος στην οποία βασίζεται το βιβλίο αυτό.

Ευχαριστώ επίσης την Stephanie Welch της Franklin Beedle & Associates, που επιμελήθηκε και σελιδοποίησε το βιβλίο στο πλαίσιο της επιμέλειας πα-ραγωγής του.

Πολλοί ήταν αυτοί που με βοήθησαν στη διάρκεια της συγγραφής διαβά-ζοντας και σχολιάζοντας προκαταρκτικές εκδοχές του βιβλίου: ο John Tang Boyland του Πανεπιστημίου του Wisconsin – Milwaukee, ο Daniel Canas του Πανεπιστημίου του Wake Forest, ο Frank Friedman του Πανεπιστη-μίου Temple, ο Assaf Khoury του Πανεπιστημίου της Βοστώνης, ο Shui Lam του Πολιτειακού Πανεπιστημίου της Καλιφόρνιας, στο Long Beach, ο Ernst

Page 22: Συγχρονες γλωσσες προγραμματισμού

xxiv ΣΥΓΧΡΟΝΕΣ ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Leiss του Πανεπιστημίου του Houston, ο Mike Morton, ο Robert Roos του Allegheny College, ο Randy Smith του Covenant College, και ο K. Vairavan του Πανεπιστημίου του Wisconsin – Milwaukee. Ιδιαίτερα ευχαριστώ τον Randy Smith, ο οποίος χρησιμοποίησε μια προκαταρκτική μορφή του βι-βλίου στα μαθήματά του στο Covenant College και μου μετέφερε πολύτιμα στοιχεία από τη χρήση του στη διδασκαλία.

Οι εναπομένουσες ατέλειες αποτελούν, φυσικά, αποκλειστικά δική μου ευθύνη.

Page 23: Συγχρονες γλωσσες προγραμματισμού

1.1. Εισαγωγή

Τα προγράμματα των υπολογιστών είναι μαγεία εν δράσει. Το κάθε πρόγραμμα μοιά­ζει με ένα περίπλοκο, αλλά και καλαίσθητο, μαγικό ξόρκι. και το καλύτερο είναι ότι με την εκτέλεση ενός προγράμματος ανακαλύπτουμε ότι τελικά τα μάγια πιάνουν! Ακόμα και όταν το πρόγραμμά μας δεν κατορθώνει ακριβώς αυτό που είχαμε κατά νου, εντούτοις κάτι κατορθώνει − πράγμα που σίγουρα δεν ισχύει για τα περισσό­τερα ξόρκια. Και η απόλαυση αυτής της έμπρακτης μαγείας είναι η δύναμη που ωθεί πολλούς αρχάριους στον προγραμματισμό, και που συνεχίζει να ανταμείβει τους έμπειρους προγραμματιστές. Ο συγγραφέας, τουλάχιστον, βιώνει αμείωτη αυτήν την απόλαυση εδώ και 20 χρόνια ενασχόλησης με τον προγραμματισμό.

Το βιβλίο αυτό πραγματεύεται τις γλώσσες προγραμματισμού. Περιέχει διδακτι­κές εισαγωγές σε τρεις γλώσσες προγραμματισμού: την ML, την Java και την Prolog.1 Οι γλώσσες αυτές είναι πολύ διαφορετικές μεταξύ τους, και αν γνωρίσετε έστω και ένα τμήμα καθεμίας από αυτές, θα έχετε τρία σαφώς διαφορετικά στίγματα στη διά­θεσή σας για να «πλοηγηθείτε» στις αρχές των γλωσσών προγραμματισμού. Εάν θελήσετε να ασχοληθείτε και πρακτικά με αυτές τις γλώσσες, δεν θα δυσκολευτείτε καθόλου: υπάρχουν καλές και δωρεάν υλοποιήσεις και για τις τρεις τους, σε ποικιλία υπολογιστικών πλαισίων. Ανάμεσα στα διδακτικά κεφάλαια θα βρείτε κεφάλαια με περισσότερο φιλοσοφικό προσανατολισμό, τα οποία πραγματεύονται με πιο αφηρη­μένο τρόπο διάφορα σοβαρά ζητήματα που αφορούν τις γλώσσες προγραμματισμού. Αν και αυτά τα κεφάλαια έχουν πιο αφηρημένο χαρακτήρα, δεν απαιτούν ιδιαίτερο μαθηματικό υπόβαθρο. Οι γλώσσες προγραμματισμού στηρίζονται, βέβαια, σε πολύ ενδιαφέροντα και ιδιαίτερα κομψά μαθηματικά, αλλά προσφέρουν επίσης άφθονο υλικό μελέτης το οποίο δεν απαιτεί μαθηματικές γνώσεις δυσπρόσιτες ή και αδιάφο­ρες σε πολλούς αναγνώστες.

1 Στα έντυπα εγχειρίδια των παλαιότερων γλωσσών, τα ονόματα των γλωσσών αναγράφονταν συνήθως με κεφαλαία γράμματα: FORTRAN, COBOL και BASIC. Στα νεώτερα εγχειρίδια, ακό­μη και σε αυτά που αφορούν διαλέκτους των παλαιότερων γλωσσών, τα ονόματα αναγράφο­νται συνήθως σε μικτή γραφή: Fortran. Η σύμβαση που ακολουθούμε σε αυτό το βιβλίο είναι η εξής: για τα ονόματα που προφέρονται σαν λέξεις (π.χ. Java και Prolog) χρησιμοποιούμε μικτή γραφή, ενώ για τα ονόματα που προφέρονται σαν ακολουθίες γραμμάτων του αγγλικού αλφα­βήτου (όπως η ML, που προφέρεται «εμ­ελ»), χρησιμοποιούμε κεφαλαιογράμματη γραφή.

Γλώσσες προγραμματισμού

1

Page 24: Συγχρονες γλωσσες προγραμματισμού

2 ΚΕΦΑΛΑΙΟ 1 − ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Πριν συνεχίσετε όμως, θα πρέπει να λάβετε υπ’ όψιν ότι το βιβλίο αυτό προϋπο­θέτει ικανοποιητική γνώση μίας τουλάχιστον γλώσσας προγραμματισμού, σε επίπε­δο που αντιστοιχεί περίπου σε μια εισαγωγή διάρκειας δύο διδακτικών εξαμήνων. Δεν έχει σημασία ποια γλώσσα γνωρίζετε. Εάν όμως δεν έχετε προγραμματίσει ποτέ στη ζωή σας, τότε αυτό το βιβλίο δεν είναι ό,τι καταλληλότερο για να αρχίσετε.

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

1.2. Η εκπληκτική ποικιλία

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

Προστακτικές γλώσσες

Ας δούμε ένα παράδειγμα προστακτικής γλώσσας, της γλώσσας C. Πρόκειται για μια συνάρτηση factorial(n), που υπολογίζει το παραγοντικό (factorial) ενός φυσικού αριθμού n:

int factorial(int n) {

int sofar = 1;

while (n > 0) sofar *= n--;

return sofar;

}

Το παραπάνω παράδειγμα περιέχει τις δύο «σφραγίδες γνησιότητας» κάθε προστα­κτικής γλώσσας: την τιμοδότηση και την επανάληψη. Η εντολή «sofar *= n--;» της γλώσσας C τιμοδοτεί τη μεταβλητή sofar. Η μεταβλητή αυτή έχει κάποια τρέ­χουσα τιμή η οποία μεταβάλλεται κάθε φορά που πραγματοποιείται μια τιμοδότηση. Η εντολή επιδρά επίσης στη μεταβλητή n, μειώνοντας κάθε φορά την τιμή της κατά μία μονάδα. Ο βρόχος «while» επαναλαμβάνει διαρκώς την εντολή. Τελικά, σε κά­ποιο βήμα αυτής της επανάληψης, η τρέχουσα τιμή της μεταβλητής n θα γίνει μηδέν, και η επανάληψη θα σταματήσει. Καθώς οι τιμές των μεταβλητών αλλάζουν σε κάθε βήμα, η σειρά εκτέλεσης των εντολών του προγράμματος έχει καίρια σημασία.

Οι έννοιες που μόλις αναφέραμε είναι τόσο στοιχειώδεις, που περνούν απαρατή­ρητες από τους περισσότερους προγραμματιστές της γλώσσας C: για αυτούς είναι προφανές ότι η σειρά εκτέλεσης των εντολών παίζει καίριο ρόλο, και εξίσου προ­φανές ότι οι τιμές των μεταβλητών μεταβάλλονται. Υπάρχουν όμως πολλές γλώσ­σες προγραμ ματισμού για τις οποίες όλα τα παραπάνω δεν έχουν κανένα νόημα. γλώσσες στις οποίες δεν υπάρχουν ούτε τιμοδοτικές εντολές, ούτε επαναληπτικές εντολές, ούτε η έννοια της αλλαγής της «τρέχουσας τιμής» μιας μεταβλητής.

Page 25: Συγχρονες γλωσσες προγραμματισμού

Συναρτησιακές γλώσσες

Ας δούμε την ίδια συνάρτηση (του παραγοντικού) υλοποιημένη στη γλώσσα ML:

fun factorial x =

if x <= 0 then 1 else x * factorial(x-1);

Το παραπάνω παράδειγμα περιλαμβάνει δύο από τις «σφραγίδες γνησιότητας» των συναρτησιακών γλωσσών: την αναδρομή και τις μονότιμες μεταβλητές2. Η αναδρο­μή είναι μια προγραμματιστική τεχνική τόσο φυσική στους προγραμματιστές της ML, όσο φυσικές είναι οι επαναληπτικές εντολές στους προγραμματιστές της C.

Η ίδια συνάρτηση υλοποιημένη στη γλώσσα Lisp θα είχε ως εξής:

(defun factorial (x)

(if (<= x 0) 1 (* x (factorial (- x 1)))))

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

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

Λογικοκεντρικές γλώσσες

Η συνάρτηση του παραγοντικού, ενώ είναι το καταλληλότερο παράδειγμα για τη γλώσσα ML, είναι ίσως το χειρότερο για την Prolog. Παρά ταύτα ας δούμε τι μορφή έχει στην Prolog:

factorial(X,1) :-

X =:= 1.

factorial(X,F) :-

X > 1,

NewX is X - 1,

factorial(NewX,NewF),

F is X * NewF.

2 Σ.τ.Μ.: Μεταβλητές από το variables − όσο βέβαια τα συμφραζόμενα επιτρέπουν να ονομάζεται «μεταβλητή» κάτι που μένει σταθερό. Οι «μεταβλητές» των συναρτησιακών γλωσσών (όπως η ML) είναι ακριβέστερα επώνυμες σταθερές, γι’ αυτό ο σχετικός όρος της ML, που θα δοθεί αργότερα, είναι val από το value = τιμή και όχι var, από το variable = μεταβλητή.

1.2 − Η ΕΚΠΛΗΚΤΙΚΗ ΠΟΙΚΙΛΙΑ 3

Page 26: Συγχρονες γλωσσες προγραμματισμού

4 ΚΕΦΑΛΑΙΟ 1 − ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Οι πρώτες δύο γραμμές εκφράζουν έναν κανόνα που επιτρέπει στο σύστημα της Prolog να συμπεράνει ότι όταν το X ισούται με 1 το παραγοντικό του X είναι 1. Οι υπόλοιπες πέντε γραμμές κώδικα καθορίζουν έναν γενικό τρόπο για να διαπιστώνει κανείς ότι το παραγοντικό του X ισούται με κάποια δεδομένη τιμή. Συγκεκριμένα: «Για να αποδείξεις ότι το παραγοντικό του X ισούται με F, αρκεί να κάνεις τα εξής: να αποδείξεις ότι το X είναι μεγαλύτερο του 1. να αποδείξεις ότι το NewX είναι μικρότερο του X κατά 1. να αποδείξεις ότι το παραγοντικό του NewX ισούται με NewF. και τέλος να αποδείξεις ότι το F ισούται με X επί NewF». Η διατύπωση ενός προγράμματος μέσω κανόνων λογικού συμπερασμού είναι η «σφραγίδα γνησιότητας» του λογικού προγραμματισμού. Αν και αυτό το είδος προγραμματισμού δεν είναι το καταλληλό­τερο για τον υπολογισμό μαθηματικών συναρτήσεων, υπάρχουν κατηγορίες προ­βλημάτων στα οποία υπερέχει ξεκάθαρα. Παραδείγματα τέτοιων προβλημάτων θα δούμε από το Κεφάλαιο 19 και παρακάτω.

Οντοστρεφείς γλώσσες

Η συνάρτηση του παραγοντικού γραμμένη στη γλώσσα Java φαίνεται σχεδόν ίδια με την εκδοχή της στη γλώσσα C. Η Java όμως είναι μια οντοστρεφής γλώσσα, πράγμα που σημαίνει ότι αφ’ ενός είναι προστακτικού τύπου, και αφ’ ετέρου έχει σχεδιαστεί ώστε να διευκολύνει την επίλυση των διαφόρων προβλημάτων μέσω οντοτήτων (ή, αλλιώς, αντικειμένων). Ονομάζουμε οντότητα μια (συνήθως μικρή) δέσμη δεδομέ­νων η οποία «γνωρίζει» πώς να χειρίζεται τον εαυτό της. Για παράδειγμα, ας δούμε τον ορισμό σε Java μιας οντότητας που φέρει έναν ακέραιο αριθμό, και «γνωρίζει» πώς να αναφέρει τόσο τον αριθμό αυτό, όσο και το παραγοντικό του.

public class MyInteger {

private int value;

public MyInteger(int value) {

this.value = value;

}

public int getValue() {

return value;

}

public MyInteger getFactorial() {

return new MyInteger(factorial(value));

}

private int factorial(int n) {

int sofar = 1;

while (n > 1) sofar *= n--;

return sofar;

}

}

Το παραπάνω παράδειγμα οντοστρεφούς προγραμματισμού φαίνεται φλύαρο σε σχέση με τα προηγούμενα, αλλά και πάλι η σύγκριση δεν είναι δίκαιη: ο οντοστρε­

Page 27: Συγχρονες γλωσσες προγραμματισμού

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

Είδαμε λοιπόν παραδείγματα από τέσσερεις οικογένειες γλωσσών: τις προστα­κτικές (όπως η C), τις συναρτησιακές (όπως η ML), τις λογικοκεντρικές (όπως η Prolog), και τις οντοστρεφείς (όπως η Java). Κάθε γλώσσα προγραμματισμού μπορεί, με λίγη προσπάθεια, να καταταγεί σε κάποια από αυτές τις τέσσερεις κατηγορίες. Αυτές οι κατηγορίες δεν είναι όμως προσδιορισμένες με αυστηρότητα, και γι’ αυτό δεν είναι πάντοτε σαφές ποιoς είναι ο ορθότερος τρόπος ταξινόμησης μιας γλώσσας. Υπάρχουν πάμπολλες γλώσσες που κινούνται στα όρια μεταξύ των κατηγοριών αυ­τών. Στην πράξη συναντάμε περισσότερες κατηγορίες γλωσσών, όχι μόνο αυτές τις τέσσερεις. Οι διάφορες γλώσσες προγραμματισμού έχουν κατά καιρούς χαρακτηρι­στεί ως εφαρμοστικές, συγχρονικές, περιοριστικές, δηλωτικές, οριστικές, διαδικα­στικές, σεναριογραφικές, μονοτιμοδοτικές και πάει λέγοντας.

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

: FACTORIAL

1 SWAP BEGIN ?DUP WHILE TUCK * SWAP 1- REPEAT ;

Η Forth είναι μια στοιβoστρεφής γλώσσα, όπως λ.χ. η PostScript είναι σελιδοστρε­φής. Η μονολεκτική εντολή SWAP της Forth εναλλάσσει τα δύο κορυφαία στοιχεία της στοίβας που διατηρεί η γλώσσα αυτή. Θα μπορούσαμε να αποκαλέσουμε την Forth προστακτική γλώσσα, αλλά αυτό δεν θα είχε ιδιαίτερο νόημα, καθώς έχει ελά­χιστα κοινά στοιχεία με τις περισσότερες άλλες προστακτικές γλώσσες.

Θεωρήστε επίσης την APL. Για να εκφραστεί η συνάρτηση παραγοντικού στη γλώσσα αυτή, αρκεί η παρακάτω έκφραση:

× / ι X

Η APL φημίζεται για τη χρήση πάμπολλων ειδικών χαρακτήρων που απουσιάζουν από τα συνηθισμένα πληκτρολόγια. Η παραπάνω έκφραση δηλώνει ότι το X θα πρέ­πει να αναπτυχθεί σε μια ακολουθία διαδοχικών ακεραίων από το 1 έως το X, και όλοι αυτοί οι αριθμοί να πολλαπλασιαστούν μεταξύ τους. (Στην πράξη, δεν θα χρειαζό­σασταν αυτήν την έκφραση, διότι στην APL μπορούμε να δηλώσουμε το παραγοντι­κό του X απλώς ως !X.) Θα μπορούσαμε να αποκαλέσουμε την APL συναρτησιακή γλώσσα, αλλά και πάλι δεν θα είχε νόημα: η APL έχει ελάχιστα κοινά σημεία με τις περισσότερες άλλες συναρτησιακές γλώσσες.

1.3. Οι παράξενες αντιμαχίες

Υπάρχουν κάποια γνωστικά αντικείμενα που φαίνονται εκ του φυσικού τους αμφι­λεγόμενα: η βιολογική εξέλιξη, η αρχική Μεγάλη Έκρηξη του σύμπαντος, η ανθρώ­πινη σεξουαλικότητα − γενικά, οποιοδήποτε θέμα απασχολεί τακτικά την επιστη­μονική στήλη της εφημερίδας The New York Times είναι βέβαιο ότι θα προκαλέσει

1.3 − ΟΙ ΠΑΡΑΞΕΝΕΣ ΑΝΤΙΜΑΧΙΕΣ 5

Page 28: Συγχρονες γλωσσες προγραμματισμού

6 ΚΕΦΑΛΑΙΟ 1 − ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

πολλές αντιδικίες. Ισχύει όμως το ίδιο και για τις γλώσσες προγραμματισμού; Το δικό μας πεδίο μελέτης σπάνια διεισδύει μέχρι τα πρωτοσέλιδα των εφημερίδων, και είναι μάλλον ελάχιστοι αυτοί που το γνωρίζουν και που ενδιαφέρονται για αυτό. Παρά ταύτα, και παραδόξως, το θέμα των γλωσσών προγραμματισμού εγείρει συχνά θερμότατες διαμάχες.

Κατ’ αρχάς, για κάθε γλώσσα προγραμματισμού θα βρείτε οπαδούς της πρόθυ­μους να υπερασπιστούν αυτήν την προτίμησή τους ενάντια σε κάθε άλλη γλώσσα. Μερικοί οπαδοί της ML «είναι στα μαχαίρια» με οπαδούς της γλώσσας Haskell. Οι οπαδοί της Forth θα πικραθούν, χωρίς πάντως να εκπλαγούν, όταν διαπιστώσουν ότι κρατούν άλλο ένα εγχειρίδιο που αγνοεί τη δική τους αγαπημένη γλώσσα. Διάφοροι οπαδοί της Prolog είναι αδύνατον να κατανοήσουν για ποιο λόγο ο λογικός προ­γραμματισμός δεν έχει υιοθετηθεί από όλους τους προγραμματιστές. Και υπάρχουν οπαδοί της Fortran πλήρως πεπεισμένοι ότι η δική τους προτίμηση δεν είναι μόνο η πρώτη ιστορικά, αλλά και η πρώτη σε σπουδαιότητα γλώσσα υψηλού επιπέδου.

Ανάμεσα στους θιασώτες της ίδιας γλώσσας ανακύπτουν διαμάχες άλλου είδους. Τα πρότυπα των γλωσσών προγραμματισμού αναπτύσσονται συχνά μέσω διεθνών επιτροπών. Ποιοι είναι οι «εγγυητές», και ποιοι συμμετέχουν τελικά σε τέτοιες δια­δικασίες αποφάσεων; Τι πρόκειται και τι δεν πρόκειται να συμπεριληφθεί στην επό­μενη επίσημη έκδοση μιας γλώσσας; Η ανάπτυξη των προδιαγραφών για κάποια γλώσσα προγραμματισμού συχνά είναι διαδικασία εντυπωσιακά αργή, περίπλοκη και... μνησίκακη.

Αυτό που ενδιαφέρει περισσότερο εμάς είναι οι συχνές διαφωνίες που αφορούν τους θεμελιώδεις ορισμούς. Έχουμε ήδη χρησιμοποιήσει τον όρο οντοστρεφής, ο οποίος είναι ένας από τους πιο έντονα αμφιλεγόμενους όρους. Ποιες ακριβώς ιδιό­τητες θα πρέπει να έχει μια γλώσσα ώστε να μπορεί να θεωρηθεί οντοστρεφής; Εμείς θα παρακάμψουμε αυτό το ερώτημα, παραθέτοντας μόνο μια άτυπη περιγραφή των οντοστρεφών γλωσσών. Θα αποφύγουμε γενικότερα να δώσουμε απολύτως αυστη­ρούς ορισμούς για τέτοιους αμφιλεγόμενους όρους, για δύο λόγους. Πρώτον, θα ήταν κάπως υποκριτικό να ισχυριστούμε ότι υπάρχει καν ορισμός, τη στιγμή που στην πραγματικότητα υπάρχουν πολλοί και ασύμβατοι ορισμοί. Και δεύτερον, διότι οι αυστηροί ορισμοί δεν θα είχαν πρακτική χρησιμότητα: ένας αυστηρός ορισμός λ.χ. για τον όρο «οντοστρεφής» απλώς θα πυροδοτούσε διαμάχες της μορφής: «η δική μου γλώσσα μου είναι οντοστρεφής ενώ η δική σου δεν είναι». Για τα ζητήματα που μας ενδιαφέρουν σε αυτό το βιβλίο, οι άτυπες περιγραφές είναι πιο χρήσιμες. Κάποιες γλώσσες είναι πράγματι πιο οντοστρεφείς από κάποιες άλλες, αλλά θα αφήσουμε τέτοια ζητήματα στη κρίση του αναγνώστη.3

3 Στους μαθηματικούς κύκλους, η ανταλλαγή σκληρών αλλά και ασαφών επιχειρημάτων αποκα­λείται συχνά «βατραχομυομαχία». Την έκφραση αυτή είχε χρησιμοποιήσει ως γνωστόν ο Albert Einstein για να χαρακτηρίσει μια έντονη διαμάχη μεταξύ των μαθηματικών David Hilbert και L.E.J. Brouwer, την οποία είχε αποκαλέσει στα γερμανικά «Frosch­Mäuse­Krieg» (δηλ. βατρα­χομυομαχία). Ο όρος προέρχεται από έναν γνωστό αρχαιοελληνικό μύθο: χρησιμοποιείται σε μια ελληνιστική παρωδία της Ιλιάδας που φέρει τον τίτλο Βατραχομυομαχία. Οι παράξενες αντιμαχίες στις γλώσσες προγραμματισμού ανήκουν συχνά στο είδος των βατραχομυομαχιών.

Page 29: Συγχρονες γλωσσες προγραμματισμού

1.4. Η αξιοπερίεργη εξέλιξη

Οι ερευνητές του κλάδου επινοούν διαρκώς καινούργιες γλώσσες προγραμματι­σμού. Ίσως όχι ακριβώς καινούργιες, αφού οι σχεδιαστές γλωσσών στηρίζονται σε ιδέες από προηγούμενες γλώσσες. Ο σχεδιαστής μιας νέας γλώσσας, όμως, έχει λυ­μένα τα χέρια του, διότι δεν δεσμεύεται από προβλήματα συμβατότητας με τυχόντα προϋπάρχοντα προγράμματα. Κάποιες νέες γλώσσες αποκτούν ευρεία απήχηση, κά­ποιες άλλες παρακμάζουν. Είτε καθιερωθούν είτε όχι, οι καινούργιες γλώσσες δια­μορφώνουν το πλαίσιο των ιδεών από το οποίο θα προέλθουν οι επόμενες γενεές γλωσσών.

Η διαδικασία σχεδίασης μιας νέας γλώσσας είναι αργή και έχει αυξητικό χα­ρακτήρα. Όλες σχεδόν οι γλώσσες, ακόμα και οι πιο νέες, αναπτύσσουν διάφορες «διαλέκτους». Λίγο πρωτύτερα μνημονεύσαμε τη σεβάσμια γλώσσα Fortran, στην πράξη όμως δεν υπάρχει «η» Fortran. Σε πρώτη φάση υπήρξαν τα αρχικά σχέδια και οι πρώτες υλοποιήσεις της Fortran από την εταιρεία IBM, που χρονολογούνται από τα μέσα της δεκαετίας του 1950. Ακολούθησε μια σειρά από πρότυπα: Fortran I, Fortran II, Fortran III, Fortran IV, Fortran 66, Fortran 77, Fortran 90, Fortran 95, και, πιθανόν Fortran 2000.4 Τα νέα πρότυπα παραγκωνίζουν τα παλαιά με βραδύ ρυθμό − και σε ορισμένες περιπτώσεις ποτέ: πολλοί προγραμματιστές χρησιμοποι­ούν ακόμα την Fortran 77. Για κάθε διάλεκτο πιθανόν να υπάρχουν διαφορετικές υλοποιήσεις για τα διάφορα συστήματα λογισμικού και υλισμικού, καθεμία από τις οποίες διευκρινίζει το αρχικό πρότυπο με διαφορετικό τρόπο. Επιπλέον, εμφανίζο­νται διάλεκτοι που εξυπηρετούν εξειδικευμένους σκοπούς: π.χ. έχουν εμφανιστεί πάνω από δέκα διάλεκτοι της Fortran που προσθέτουν σε αυτήν ειδικές γλωσσικές δυνατότητες για παράλληλο προγραμματισμό.

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

1.5. Οι πολλαπλές διασυνδέσεις

Το βιβλίο αυτό πραγματεύεται τις ίδιες τις γλώσσες προγραμματισμού, και όχι τον καθαυτό προγραμματισμό, δηλαδή το πώς να γράφετε καλά προγράμματα. Μερι­κές φορές βέβαια θα σχολιάσουμε και ζητήματα που αφορούν το προγραμματιστι­κό ύφος, διότι οι γλώσσες δεν μένουν ουδέτερες σε αυτό το θέμα. Κάθε γλώσσα

4 Οι επιτροπές τυποποίησης συχνά είναι υπεραισιόδοξες ως προς τις ονομασίες που δίνουν στα σχέδιά τους: Το πρότυπο Fortran 90 ονομάστηκε διαδοχικά Fortran 82, 8X, και 88, πριν κυκλο­φορήσει τελικά ως Fortran 90 (εντός του 1991!). Το πρότυπο Fortran 2000 είχε ανακοινωθεί ότι θα κυκλοφορήσει εντός του 2002.

1.5 − ΟΙ ΠΟΛΛΑΠΛΕΣ ΔΙΑΣΥΝΔΕΣΕΙΣ 7

Page 30: Συγχρονες γλωσσες προγραμματισμού

8 ΚΕΦΑΛΑΙΟ 1 − ΓΛΩΣΣΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

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

Από τη μία πλευρά, οι γλώσσες προγραμματισμού κατευθύνουν τον προγραμ­ματιστή προς ένα συγκεκριμένο ύφος προγραμματισμού. Οι οντοστρεφείς γλώσσες, όπως η Java, ωθούν τους προγραμματιστές να χρησιμοποιούν οντότητες. Οι συ­ναρτησιακές γλώσσες, όπως η ML, οδηγούν τους προγραμματιστές προς ένα ύφος προγραμματισμού που βασίζεται σε πολλές μικρές συναρτήσεις. Οι λογικοκεντρικές γλώσσες, όπως η Prolog, ενθαρρύνουν τους προγραμματιστές να εκφράζουν τη λύ­ση των προβλημάτων ως αναζήτηση σε ένα λογικώς προσδιορισμένο σύνολο ενδε­χόμενων λύσεων. Το να γράφετε προγράμματα σε ύφος αναντίστοιχο με τη γλώσσα που χρησιμοποιείτε είναι μεν εφικτό, αλλά σίγουρα δεν είναι καλή πρακτική. Μπο­ρείτε να συντάξετε προστακτικά προγράμματα με βρόχους και τιμοδοτήσεις ακό­μα και στην ML (αν και αυτό το βιβλίο δεν πρόκειται να σας εξηγήσει πώς γίνεται αυτό!). Μπορείτε να γράψετε προγράμματα Java τα οποία δεν δημιουργούν ούτε μία οντότητα και απλώς ενσωματώνουν έναν μεγάλο όγκο συνηθισμένου προστα­κτικού κώδικα στον ορισμό μιας μοναδικής κλάσης οντοτήτων. Στην Java, όπως και σε οποιαδήποτε άλλη γλώσσα που υποστηρίζει αναδρομή, είναι δυνατόν να γράψε­τε συναρτησιακά προγράμματα χωρίς επαναληπτικές εντολές ή τιμοδοτήσεις. Όλα τα παραπάνω όμως δεν είναι παρά οι εξαιρέσεις που επιβεβαιώνουν τον κανόνα: όταν προγραμματίζετε σε ύφος αφύσικο προς τη γλώσσα εργασίας, όταν δηλαδή αντιμάχεστε τον χαρακτήρα αυτής της γλώσσας, θα νοιώσετε ότι η ίδια η γλώσσα αντιστέκεται.

Από την άλλη πλευρά, η προγραμματιστική πρακτική οδηγεί συχνά τους προγραμ­ματιστές προς νέες ιδέες όσον αφορά τις γλώσσες. Για παράδειγμα, ο John McCarthy εισήγαγε στη Lisp την αναδρομή και τις υποθετικές εκφράσεις, διότι διαπίστωσε ότι ήταν απαραίτητες για τις εφαρμογές τεχνητής νοημοσύνης που ανέπτυσσε. Οι «κλά­σεις» και οι «οντότητες» εισήχθησαν στη Simula διότι οι σχεδιαστές της, Kristen Nygaard και Ole­Johan Dahl, τις χρειάζονταν για τις μεγάλες προσομοιώσεις που υλοποιούσαν. Στο Κεφάλαιο 24 θα αναφέρουμε και άλλα τέτοια περιστατικά από την ιστορία των γλωσσών προγραμματισμού.

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

Page 31: Συγχρονες γλωσσες προγραμματισμού

1.6. Σύντομο σχόλιο για τις Διεπαφές για Προγραμματισμό Εφαρμογών

Οι σύγχρονες εμπορικές γλώσσες προγραμματισμού υποστηρίζονται από μεγάλες και τυποποιημένες βιβλιοθήκες έτοιμου κώδικα, τις λεγόμενες Διεπαφές για Προ‑γραμματισμό Εφαρμογών (ΔιΠΕ). Μια ΔιΠΕ είναι δυνατόν να περιέχει κώδικα που υλοποιεί βασικές δομές δεδομένων (στοίβες, ουρές, πίνακες διασποράς, κ.λπ.), δι­διάστατα και τριδιάστατα γραφικά, γραφιστικές διεπαφές εργασίας, υποστήριξη δι­κτύου, διαχείριση αρχείων, κρυπτογράφηση και ασφάλεια, και πολλές άλλες υπηρε­σίες. Η αφομοίωση των περιεχομένων και του τρόπου χρήσης κάποιας ΔιΠΕ είναι από τα βασικά καθήκοντα των μαχόμενων προγραμματιστών. Η έντυπη περιγραφή των προδιαγραφών μιας γλώσσας συχνά έχει μικρότερο μέγεθος από την έντυπη τεκμηρίωση μιας ΔιΠΕ.

Αναφέρουμε εδώ τις Διεπαφές για Προγραμματισμό Εφαρμογών για να τις αγνο­ήσουμε. Αν και είναι σημαντικότατες, δεν είναι το αντικείμενό μας. Στα διδακτικά κεφάλαια αυτού του βιβλίου περί ML, Java και Prolog θα βρείτε αρκετές πληροφορί­ες ώστε να είστε σε θέση να λύνετε απλά προβλήματα. Για την ανάπτυξη εφαρμογών μεγάλης κλίμακας θα χρειαστείτε βαθύτερη γνώση των αντίστοιχων ΔιΠΕ, η οποία δεν εμπίπτει στους στόχους αυτού του βιβλίου.

1.7. Ανακεφαλαίωση

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

Στο κεφάλαιο αυτό περιγράψαμε επίσης τη δομή αυτού του βιβλίου: είναι ένα μείγμα από πρακτικά­διδακτικά και θεωρητικά κεφάλαια. Όλα τα κεφάλαια αυτού του βιβλίου −εκτός από το πρώτο και το τελευταίο− έχουν στο τέλος τους κάποιες ασκήσεις. Πολλά περιλαμβάνουν και μια ενότητα με βιβλιογραφικές υποδείξεις για περαιτέρω μελέτη.

Το επόμενο κεφάλαιο είναι το πρώτο από τα θεωρητικά. Ασχολείται με το πώς ορί­ζουμε τη σύνταξη μιας γλώσσας προγραμματισμού. (Το πρώτο πρακτικό­διδακτικό κεφάλαιο είναι το 5, και αφορά τη συναρτησιακή γλώσσα ML.)

1.7 − ΑΝΑΚΕΦΑΛΑΙΩΣΗ 9

Page 32: Συγχρονες γλωσσες προγραμματισμού
Page 33: Συγχρονες γλωσσες προγραμματισμού

2.1. Εισαγωγή

Τα απλούστερα ερωτήματα σχετικά με μια γλώσσα προγραμματισμού είναι συνήθως ερωτήματα του τύπου: Τι μορφή έχουν οι εκφράσεις, ή οι εντολές, ή οι συναρτήσεις; Πώς οριοθετούνται τα σχόλια; Πού τοποθετούνται οι «άνω τελείες»; Τα ζητήματα αυτά αφορούν τη σύνταξη, δηλαδή τους συντακτικούς κανόνες μιας γλώσσας προ­γραμματισμού.

Η σύνταξη (οι συντακτικοί κανόνες) μιας γλώσσας προγραμματισμού είναι εκείνο το τμήμα του ορισμού της γλώσσας που περιγράφει την όψη ενός προγράμματος, δηλαδή τη μορφή και τη δομή του.

Τα πιο δύσκολα ερωτήματα αφορούν ζητήματα συμπεριφοράς: Τι κάνει μια δεδομένη έκφραση, εντολή ή συνάρτηση; Πώς «δουλεύει»; Ποιες παρενέργειες είναι δυνατόν να προκύψουν κατά την εκτέλεσή της; Τα ζητήματα αυτά αφορούν τη σημασιολογία, δηλαδή τους σημασιολογικούς κανόνες μιας γλώσσας προγραμματισμού.

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

Στο κεφάλαιο αυτό θα εισαγάγουμε τις τυπικές γραμματικές, το εργαλείο μέσω του οποίου ορίζεται η σύνταξη μιας γλώσσας προγραμματισμού. (Μία από τις τυπι­κές τεχνικές ορισμού της σημασιολογίας των γλωσσών προγραμματισμού παρουσιά­ζεται στο Κεφάλαιο 23.) Όταν ολοκληρώσετε το τρέχον κεφάλαιο θα πρέπει να είστε σε θέση όχι μόνο να κατανοείτε τις τυπικές γραμματικές, αλλά και να σχεδιάζετε μόνοι σας απλές τέτοιες γραμματικές.

2.2. Ενδεικτική γραμματική για την αγγλική γλώσσα

Ας αρχίσουμε με μια απλή γραμματική για την αγγλική γλώσσα. Θα θεωρούμε άρθρο καθεμία από τις λέξεις a και the, και θα το συμβολίζουμε με <Α>. Ο ορισμός αυτός διατυπώνεται ως εξής:

Ο ορισμός των συντακτικών κανόνων

2

Page 34: Συγχρονες γλωσσες προγραμματισμού

<Α> ::= a | the

Θα θεωρούμε ουσιαστικό, το οποίο θα συμβολίζουμε με <O>, καθεμία από τις λέξεις: dog, cat, και rat:

<O> ::= dog | cat | rat

Μια ονοματική φράση, <ΟΦ>, είναι ένα άρθρο ακολουθούμενο από ένα ουσιαστικό:

<ΟΦ> ::= <Α> <O>

Θα θεωρούμε ρήματα, τα οποία θα συμβολίζουμε με <Ρ>, τις λέξεις loves, hates, και eats:

<Ρ> ::= loves | hates | eats

Και τέλος, θα ορίσουμε ως πρόταση, <Π>, μια ονοματική φράση, ακολουθούμενη από ένα ρήμα, ακολουθούμενο από μία ακόμα ονοματική φράση.

<Π> ::= <ΟΦ> <Ρ> <ΟΦ>

Όλοι μαζί οι παραπάνω κανόνες συνιστούν μια γραμματική που ορίζει ένα μικρό τμήμα της αγγλικής γλώσσας (χωρίς σημεία στίξης):

<Π> ::= <ΟΦ> <Ρ> <ΟΦ>

<ΟΦ> ::= <Α> <O>

<Ρ> ::= loves | hates | eats <O> ::= dog | cat | rat

<Α> ::= a | the

Με ποιο τρόπο το παραπάνω σύνολο κανόνων (δηλαδή η παραπάνω γραμματική) ορίζει μια γλώσσα; Θα θεωρήσουμε τη γραμματική ως ένα σύνολο οδηγιών για την κατασκευή «δένδρων». Θα τοποθετήσουμε το εναρκτήριο σύμβολο <Π> στη ρίζα του δένδρου, και θα θεωρήσουμε ότι οι κανόνες της γραμματικής προσδιορίζουν τον τρόπο με τον οποίο εκφύονται θυγατρικοί κόμβοι από πατρικούς κόμβους του δέν­δρου. Τα δένδρα που κατασκευάζονται με αυτό τον τρόπο ονομάζονται συντακτικά δένδρα και είθισται να σχεδιάζονται ανάποδα (προς τα κάτω), όπως στο ακόλουθο παράδειγμα:

<Π>

<Ρ>

loves

the dog the cat

<ΟΦ><ΟΦ>

<O><Α> <O><Α>

Σχήμα 2.1: Ενδεικτικό συντακτικό δένδρο.

Οι θυγατρικοί κόμβοι κάθε κόμβου προκύπτουν με την εφαρμογή κάποιου κανόνα (και μόνον με αυτόν τον τρόπο). Π.χ., ένας κόμβος τύπου <ΟΦ> θα πρέπει να έχει δύο θυγατρικούς, έναν τύπου <Α> και έναν τύπου <Ο>, σύμφωνα με τον κανόνα

12 ΚΕΦΑΛΑΙΟ 2 − Ο ΟΡΙΣΜΟΣ ΤΩΝ ΣΥΝΤΑΚΤΙΚΩΝ ΚΑΝΟΝΩΝ

Page 35: Συγχρονες γλωσσες προγραμματισμού

<ΟΦ> ::= <Α> <Ο>. Αν ελέγξετε το παραπάνω συντακτικό δένδρο, θα διαπιστώσετε ότι όλοι οι κλάδοι του αναπτύσσονται σύμφωνα με την αρχή που μόλις περιγράψαμε.

Διαβάζοντας το φύλλωμα του δένδρου (τους κόμβους στους οποίους καταλή­γουν οι διάφοροι κλάδοι), λαμβάνουμε την πρόταση την οποία ορίζει το δένδρο. Για το παραπάνω δένδρο η πρόταση είναι η εξής: «the dog loves the cat». Στο επό­μενο σχήμα δίνουμε ένα διαφορετικό συντακτικό δένδρο, κατασκευασμένο με βάση τους ίδιους κανόνες. Σύμφωνα με αυτό το δένδρο, η πρόταση «a cat eats the rat» ανήκει επίσης στα «αγγλικά» μας.

<Π>

<Ρ>

eats

a cat the rat

<ΟΦ><ΟΦ>

<Ο><Α> <Ο><Α>

Σχήμα 2.2: Άλλο ένα συντακτικό δένδρο, με την αντίστοιχη πρόταση.

Η γλώσσα που ορίζεται από μια γραμματική είναι το σύνολο των «προτάσεων» (=συμ­βο λοσειρών) που σχηματίζονται στα φυλλώματα των συντακτικών δένδρων που παράγει η γραμματική.

2.3. Ενδεικτική γραμματική για μια γλώσσα προγραμματισμού

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

<έκφραση> ::= <έκφραση> + <έκφραση> | <έκφραση> * <έκφραση> | ( <έκφραση> )

| α | β | γ

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

α

α + β

α + β * γ

((α + β) * γ)

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

Η εύρεση ενός συντακτικού δένδρου για κάποια δεδομένη συμβολοσειρά, και ως προς κάποια δεδομένη γραμματική, ονομάζεται συντακτική ανάλυση της συμβο­λοσειράς. Τα διάφορα γλωσσικά συστήματα είναι αναγκασμένα να προβαίνουν σε

2.3 − ΕΝΔΕΙΚΤΙΚΗ ΓΡΑΜΜΑΤΙΚΗ ΓΙΑ ΜΙΑ ΓΛΩΣΣΑ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ 13

Page 36: Συγχρονες γλωσσες προγραμματισμού

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

Ορισμένες γραμματικές δίνουν περισσότερα από ένα συντακτικά δένδρα για την ίδια συμβολοσειρά. Θα εξετάσουμε στο Κεφάλαιο 3 γιατί αυτό αποτελεί πρόβλημα και πώς μπορεί να αντιμετωπιστεί. Προς το παρόν ο στόχος μας είναι απλώς να ορίσουμε τη γλώσσα που έχουμε κατά νου. Εφ’ όσον οι κανόνες της γραμματικής επιτρέπουν την ύπαρξη έστω και ενός συντακτικού δένδρου για μια δεδομένη σειρά λεξιμορίων, αυτή η σειρά ανήκει εξ ορισμού στη σχετική γλώσσα.

2.4. Ορισμός μιας γραμματικής: η μορφή ΒΝ

Έχοντας πλέον δει δύο συγκεκριμένα παραδείγματα, μπορούμε να ορίσουμε ακρι­βέστερα τι εννοούμε λέγοντας «γραμματική»: Μια γραμματική έχει τέσσερεις ση­μαντικές συνιστώσες: ένα σύνολο λεξιμορίων, ένα σύνολο παραγωγικών συμβόλων, ένα σύνολο κανόνων παραγωγής, και ένα διακεκριμένο εναρκτήριο σύμβολο. Στο Σχήμα 2.4 υποδεικνύονται οι συνιστώσες αυτές για το παράδειγμα της «αγγλικής γραμματικής».

<Π> ::= <ΟΦ> <Ρ> <ΟΦ>

<ΟΦ> ::= <Α> <Ο>

<Ρ> ::= loves | hates | eats

<Ο> ::= dog | cat | rat

<A> ::= a | the

εναρκτήριο σύμβολο κανόνας παραγωγής

παραγωγικά σύμβολα

λεξιμόρια

Σχήμα 2.4: Οι συνιστώσες της αγγλικής «γραμματικής».

14 ΚΕΦΑΛΑΙΟ 2 − Ο ΟΡΙΣΜΟΣ ΤΩΝ ΣΥΝΤΑΚΤΙΚΩΝ ΚΑΝΟΝΩΝ

<έκφραση>

<έκφραση>

*

)(

<έκφραση> <έκφραση>

α β

Y<έκφραση> )(

+<έκφραση> <έκφραση>

Σχήμα 2.3: Το συντακτικό δένδρο της έκφρασης ((α + β) * γ), κατά τη γραμματική του κειμένου.

Page 37: Συγχρονες γλωσσες προγραμματισμού

Τα λεξιμόρια είναι οι μικρότερες συντακτικές μονάδες. Είναι εκείνες οι «λέξεις» για τις οποίες ορίζουμε ότι δεν επιδέχονται περαιτέρω ανάλυση σε μικρότερους γλωσ­σικούς όρους. Στο παράδειγμά μας έχουμε επιλέξει να θεωρήσουμε τη λέξη cat ως λεξιμόριο, ακριβώς όπως στις διάφορες γλώσσες προγραμματισμού επιλέγουμε να θεωρούμε τις λέξεις­κλειδιά1 (όπως if), ή τα ονόματα (όπως john), ή τους τελεστές (όπως!=) ως λεξιμόρια.

Τα παραγωγικά σύμβολα είναι όροι που οριοθετούμε περικλείοντάς τους σε γω­νιώδεις παρενθέσεις, π.χ. <ΟΦ>. Τα σύμβολα αυτά αντιστοιχούν σε διάφορα είδη γλωσσικών δομών. Ενδεικτικές τέτοιες δομές της αγγλικής γλώσσας είναι οι προτά­σεις και οι ονοματικές φράσεις, ενώ των γλωσσών προγραμματισμού οι εντολές και οι εκφράσεις. Σε κάθε γραμματική, ορίζεται ένα συγκεκριμένο παραγωγικό σύμβολο ως ρίζα κάθε συντακτικού δένδρου: είναι το λεγόμενο εναρκτήριο σύμβολο.

Οι κανόνες παραγωγής αποτελούνται από δύο «πλευρές» (την αριστερή και τη δεξιά), και το διαχωριστικό σύμβολο ::= (τοποθετημένο ανάμεσά τους). Η αριστε­ρή πλευρά ενός κανόνα παραγωγής αποτελείται από ένα παραγωγικό σύμβολο και η δεξιά πλευρά από μια ακολουθία ενός ή περισσοτέρων συμβόλων, καθένα εκ των οποίων είναι είτε ένα λεξιμόριο είτε ένα παραγωγικό σύμβολο της γλώσσας. Αυτοί οι κανόνες μας προσδιορίζουν τους δυνατούς τρόπους επαύξησης των συντακτικών δένδρων: μας επιτρέπουν να τοποθετούμε κατά σειρά κάτω από έναν κόμβο που φέ­ρει το παραγωγικό σύμβολο της αριστερής πλευράς την ακολουθία των συμβόλων που εμφανίζονται στη δεξιά πλευρά, μετατρέποντας καθένα από αυτά τα σύμβολα σε θυγατρικό κόμβο.

Όταν τυχαίνει πολλοί κανόνες παραγωγής να έχουν το ίδιο παραγωγικό σύμβο­λο στην αριστερή πλευρά, μας διευκολύνει, για λόγους οικονομίας γραφής, να τους δηλώνουμε συντομογραφικά όλους μαζί ως εξής: Γράφουμε μία φορά την (κοινή) αριστερή πλευρά, κατόπιν το διαχωριστικό σύμβολο ::=, και στη συνέχεια παραθέ­τουμε τις δεξιές πλευρές μία προς μία διαχωρισμένες από το σύμβολο της «καθέτου», |. Η γραφή αυτή έχει απλώς και μόνο συντομογραφικό νόημα, και ο στενογραφημέ­νος κανόνας θεωρείται απολύτως ισοδύναμος με το σύνολο των αρχικών κανόνων. Ας ξαναγράψουμε τη γραμματική για την απλή γλώσσα των εκφράσεων που περι­γράψαμε προηγουμένως, χρησιμοποιώντας αυτήν τη συντομογραφική τεχνική:

<έκφραση> ::= <έκφραση> + <έκφραση> | <έκφραση> * <έκφραση> | ( <έκφραση> )

| α | β | γ

Χωρίς τη συντομογραφική σύμβασή μας θα έπρεπε να γράψουμε:

<έκφραση> ::= <έκφραση> + <έκφραση> <έκφραση> ::= <έκφραση> * <έκφραση> <έκφραση> ::= ( <έκφραση> ) <έκφραση> ::= α <έκφραση> ::= β <έκφραση> ::= γ

1 Σ.τ.Μ.: κλειδωνύμια, εφεξής.

2.4 − ΟΡΙΣΜΟΣ ΜΙΑΣ ΓΡΑΜΜΑΤΙΚΗΣ: Η ΜΟΡΦΗ ΒΝ 15

Page 38: Συγχρονες γλωσσες προγραμματισμού

Και μια τελευταία λεπτομέρεια: συχνά μας εξυπηρετεί να συμπεριλάβουμε στα παρα­γωγικά σύμβολα ένα ειδικό σύμβολο <κενό> το οποίο υποδηλώνει το κενό, δηλαδή μια σειρά από «μηδέν» το πλήθος λεξιμόρια. Για παράδειγμα, μια εντολή if­then στην οποία το εναλλακτικό τμήμα else είναι προαιρετικό μπορεί να οριστεί γραμ­ματικά ως εξής:

<υποθετική εντολή> ::= if <έκφραση> then <εντολή> <εναλλακτικό μέρος> <εναλλακτικό μέρος> ::= else <εντολή> | <κενό>

Αυτός ο τρόπος γραφής μιας γραμματικής αναπτύχθηκε από τους John Backus και Peter Naur περί το 1960. Στις τεχνικές αναφορές τους σχετικά με την ανάπτυξη της γλώσσας Algol χρησιμοποίησαν αυτόν τον τρόπο για να περιγράψουν τη σύ­νταξη της γλώσσας. Αυτός ο συμβολισμός αποκαλείται πια, προς τιμή τους, μορφή Backus‑Naur (μορφή BN). Στα προηγούμενα παραδείγματά μας χρησιμοποιήσαμε τη μορφή Backus­Naur, την οποία θα συνεχίσουμε να χρησιμοποιούμε και στο υπό­λοιπο του βιβλίου.

2.5. Η σχεδίαση μιας γραμματικής

Η σχεδίαση μιας γραμματικής μοιάζει με τη συγγραφή ενός προγράμματος: είναι και τα δύο απαιτητικές διανοητικές ασκήσεις. Κάθε πρόγραμμα είναι μια πεπερασμέ­νη, δομημένη και μηχανική οντότητα που ορίζει μια ενδεχομένως άπειρη συλλογή εκτελεστικών συμπεριφορών. Όταν γράφουμε ένα πρόγραμμα, θα πρέπει να είμαστε σε θέση να φανταστούμε με ποιον τρόπο θα εκτυλιχθεί αυτό το κατασκεύασμά μας από τη στιγμή που θα αρχίσει να εκτελείται. Εντελώς ανάλογα, μια γραμματική εί­ναι μια πεπερασμένη, δομημένη και μηχανική οντότητα σχεδιασμένη με σκοπό να προσδιορίσει μια ενδεχομένως άπειρη γλώσσα. Όταν διαμορφώνουμε μια γραμμα­τική, θα πρέπει να είμαστε σε θέση να φανταστούμε με ποιον τρόπο θα εκτυλιχθούν οι κανόνες παραγωγής που θέτουμε καθώς θα κατασκευάζονται τα αντίστοιχα συντακτικά δένδρα. Η μορφή Backus­Naur είναι αρκετά απλή, αλλά η συγγραφή των ορισμών Backus­Naur για τις διάφορες δομές που εμφανίζονται στις γλώσσες προγραμματισμού απαιτεί πρακτική εξάσκηση. Δεν υπάρχει πάντως λόγος ανησυ­χίας − τελικά, είναι πιο εύκολο να σχεδιάζει κάποιος γραμματικές, παρά να γράφει προγράμματα!

Η πιο χρήσιμη συμβουλή προς αυτή την κατεύθυνση είναι η γνωστή τακτική «διαίρει και κυρίευε». Τόσο στις γραμματικές όσο και στον προγραμματισμό, έχει καίρια σημασία η ανάλυση των προβλημάτων μας σε μικρότερα και απλούστερα υποπροβλήματα. Ας δούμε ένα παράδειγμα από τη γλώσσα Java, και συγκεκριμένα την εντολή της Java που ορίζει τοπικές μεταβλητές. Ιδού τρεις τέτοιες εντολές:

float a;

boolean a,b,c;

int a=1, b, c=1+2;

Οι εντολές αυτές αποτελούνται από ένα όνομα τύπου, που ακολουθείται από έναν κατάλογο ενός ή περισσοτέρων ονομάτων μεταβλητών. Τα ονόματα αυτά των μετα­

16 ΚΕΦΑΛΑΙΟ 2 − Ο ΟΡΙΣΜΟΣ ΤΩΝ ΣΥΝΤΑΚΤΙΚΩΝ ΚΑΝΟΝΩΝ

Page 39: Συγχρονες γλωσσες προγραμματισμού

βλητών χωρίζονται μεταξύ τους με κόμμα(τα), ενώ οι εντολές ολοκληρώνονται με μια άνω τελεία (αγγλικού τύπου, δηλαδή «;»). Κάθε όνομα μεταβλητής ενδέχεται να ακολουθείται από το σημείο της ισότητας και μια έκφραση· η συντακτική αυτή δο­μήχρησιμοποιείται για να «πρωτοτιμοδοτήσει» τη μεταβλητή, δηλαδή να καθορίσει την αρχική τιμή της.

Ας προσπαθήσουμε να καταγράψουμε τη γραμματική των παραπάνω εντολών σε μορφή Backus­Naur. Θα χρησιμοποιήσουμε ως εναρκτήριο σύμβολο τη <δήλωση μεταβλητών>, και το πρώτο μας βήμα θα είναι να αναγάγουμε το πρόβλημά μας σε μικρότερα επιμέρους προβλήματα. Οι βασικές συνιστώσες είναι το όνομα ενός τύ­που, ο κατάλογος των μεταβλητών και τέλος η άνω τελεία. Τα δύο πρώτα απαιτούν περαιτέρω ανάλυση, και επομένως θα χρησιμοποιήσουμε για αυτά κάποια παραγω­γικά σύμβολα. Έχουμε λοιπόν τον εξής κανόνα παραγωγής:

<δήλωση μεταβλητών> ::= <όνομα τύπου> <κατάλογος δηλωτικών> ;

Ως ονόματα τύπων θα δεχθούμε τους βασικούς τύπους της Java (παραλείποντας τις ονομασίες κλάσεων, τις ονομασίες διεπαφών, και τις συστοιχίες, που θα χρειάζονταν για μια πλήρη γραμματική της Java).

<όνομα τύπου> ::= boolean | byte | short | int | long | char | float | double

Δεν μένει παρά να ορίσουμε τον <κατάλογο δηλωτικών>. Ο ορισμός αυτός είναι και πάλι αρκετά περίπλοκος, οπότε θα χρειαστεί να αναλύσουμε ξανά το πρόβλημα σε μικρότερα. Κάθε κατάλογος δηλωτικών είναι μια σειρά από ένα ή περισσότερα δη­λωτικά που χωρίζονται μεταξύ τους με κόμματα. Η δομή αυτή μπορεί να περιγραφεί ως εξής:

<κατάλογος δηλωτικών> ::= <δηλωτικό> | <δηλωτικό> , <κατάλογος δηλωτικών>

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

Θα πρέπει στη συνέχεια να αναλύσουμε τον όρο <δηλωτικό>: αυτός αποτελείται από ένα όνομα μεταβλητής που ακολουθείται, προαιρετικά, από το σημείο της ισό­τητας και μια έκφραση. Η αντίστοιχη μορφή ΒΝ έχει ως εξής:

<δηλωτικό> ::= <όνομα μεταβλητής> | <όνομα μεταβλητής> = <έκφραση>

Εάν θα θέλαμε να γράψουμε μια πλήρη γραμματική της Java, θα έπρεπε να επιτρέ­ψουμε το κάθε όνομα μεταβλητής να ακολουθείται από ένα ζεύγος αγκυλών (για να υπάρχει η δυνατότητα να ορίζονται συστοιχίες μεταβλητών), και επιπλέον να προβλέπαμε κάποιο τρόπο πρωτοτιμοδότησης των συστοιχιών (δεξιά από το ση­μείο της ισότητας). Θα έπρεπε επίσης να δηλώσουμε τι θεωρούμε έγκυρα ονόματα μεταβλητών και έγκυρες εκφράσεις, αλλά τα όσα είπαμε αρκούν προς το παρόν.

2.5 − Η ΣΧΕΔΙΑΣΗ ΜΙΑΣ ΓΡΑΜΜΑΤΙΚΗΣ 17

Page 40: Συγχρονες γλωσσες προγραμματισμού

Μια τελευταία σημαντική συμβουλή: αφού συντάξετε τη γραμματική σας, υπο­βάλετέ την σε έλεγχο όπως θα κάνατε με ένα πρόγραμμα. Λ.χ. στο παράδειγμα που δώσαμε για τη Java αρχίσαμε με μια σειρά εντολών. Είναι δυνατόν να αναλύσουμε αυτές τις εντολές με βάση τους κανόνες που γράψαμε; Και όχι μόνο αυτό: θα πρέπει να βεβαιωθούμε πως ό,τι είναι δυνατόν να γραφτεί με βάση αυτούς τους κανόνες είναι πράγματι αποδεκτό για μας. Μην παραλείψετε αυτόν τον τελευταίο έλεγχο αν ασχοληθείτε με τις ασκήσεις που δίνονται στο τέλος αυτού του κεφαλαίου για τη σχεδίαση γραμματικών.

2.6. Η λεκτική και η φραστική δομή μιας γλώσσας

Οι γραμματικές που εξετάσαμε έως τώρα ορίζουν μια γλώσσα μέσω λεξιμορίων όπως είναι τα ονόματα, τα κλειδωνύμια και οι τελεστές. Ένα πρόγραμμα, όμως, αποθηκεύ­εται συνήθως όχι σαν μια ακολουθία λεξιμορίων, αλλά σαν ένα αρχείο απλού κειμέ­νου, δηλαδή σαν μια (συνήθως μακρά) ακολουθία από χαρακτήρες, όπως γράμματα του κοινού αλφαβήτου, αριθμητικά ψηφία, διάκενα, στηλοθέτες, γραμμοληκτικούς χαρακτήρες κ.λπ. Πώς αναλύεται μια τέτοια σειρά σε λεξιμόρια;

Μια γραμματική της οποίας τα λεξιμόρια δεν είναι μεμονωμένοι χαρακτήρες, αλλά συμπλέγματα, όπως ονόματα, κλειδωνύμια και τελεστές, είναι ημιτελής. Ορίζει μόνο τη φραστική δομή της γλώσσας περιγράφοντας τον τρόπο κατασκευής συντα­κτικών δένδρων με λεξιμόρια στα φυλλώματά τους. Δεν ορίζει όμως τη λεκτική δομή της γλώσσας, δηλαδή το πώς αναλύεται το κείμενο του προγράμματος σε αυτά τα λεξιμόρια.

Είναι βέβαια δυνατόν να ενοποιήσουμε τις δύο δομές σχεδιάζοντας μια ενιαία γραμματική της οποίας τα λεξιμόρια είναι μεμονωμένοι χαρακτήρες, αλλά αυτό δεν το κάνουμε σχεδόν ποτέ, διότι μια τέτοια γραμματική είναι τρομερά δύσμορφη και δυσανάγνωστη. Αρκεί να αναφέρουμε ως παράδειγμα το ζήτημα του κενού χώρου. Σχεδόν κάθε σύγχρονη γλώσσα προγραμματισμού επιτρέπει να παρεμβάλλεται με­ταξύ των λεξιμορίων κενός χώρος, όπως διάκενα, στηλοθέτες, γραμμοληκτικοί χαρα­κτήρες κ.λπ. Ο ορισμός μιας τέτοιας γλώσσας ενοποιημένης και πλήρους έως το επί­πεδο των μεμονωμένων χαρακτήρων θα έπρεπε να εμπλέκει αυτούς τους «κενούς» χαρακτήρες σχεδόν σε κάθε κανόνα του. Ο ορισμός μας για την εντολή if­then θα έμοιαζε τελικά κάπως έτσι:

<υποθετική εντολή> ::= if <κενός χώρος> <έκφραση> <κενός χώρος> then <κενός χώρος> <εντολή> <κενός χώρος> <εναλλακτικό μέρος> <εναλλακτικό μέρος> ::= else <κενός χώρος> <εντολή> | <κενό>

Και η πραγματική κατάσταση είναι ακόμα χειρότερη, διότι ανάμεσα σε ορισμένα λε­ξιμόρια είναι απαραίτητο να υπάρχει κενός χώρος (λ.χ., στις περισσότερες γλώσσες το then p διαφέρει από το thenp), ενώ ανάμεσα σε άλλα όχι (λ.χ., στις περισσότερες γλώσσες το a+b ισοδυναμεί με το a + b). Εκτός αυτών, υπάρχουν και τα σχόλια, τα οποία στις περισσότερες σύγχρονες γλώσσες είναι δυνατόν να παρεμβάλλονται σχε­δόν παντού, όπως ο κενός χώρος. Μια γραμματική που θα προέβλεπε χαρακτήρα προς χαρακτήρα όλα τα προηγούμενα θα ήταν ακατάληπτη.

18 ΚΕΦΑΛΑΙΟ 2 − Ο ΟΡΙΣΜΟΣ ΤΩΝ ΣΥΝΤΑΚΤΙΚΩΝ ΚΑΝΟΝΩΝ

Page 41: Συγχρονες γλωσσες προγραμματισμού

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

<αρχείο προγράμματος> ::= <τέλος αρχείου> | <στοιχείο> <αρχείο προγράμματος> <στοιχείο> ::= <λεξιμόριο> | <απλός κενός χώρος> | <σχόλιο> <απλός κενός χώρος> ::= <διάκενο> | <στηλοθέτης> | <γραμμοληκτικό> <λεξιμόριο> ::= <όνομα> | <τελεστής> | <σταθερά> | …

(Το παράδειγμα είναι εμφανώς ημιτελές: θα πρέπει κανείς να προχωρήσει έως ότου ορίσει όλα αυτά τα παραγωγικά σύμβολα σε επίπεδο χαρακτήρων, όπως αυτοί από τους οποίους αποτελούνται τα αρχεία κειμένου.) Όπως μπορείτε να παρατηρήσετε, δεν υπάρχουν γλωσσικές δομές σε επίπεδο φράσης, ούτε εκφράσεις ή εντολές. Η γραμματική περιγράφει απλώς το πώς ένα αρχείο αναλύεται σε μια σειρά από λεξι­μόρια και άλλα στοιχεία.

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

Η πολυετής εμπειρία στο πεδίο της σχεδίασης και υλοποίησης γλωσσών προ­γραμματισμού έχει δείξει ότι ο διαχωρισμός του λεκτικού από το φραστικό επίπεδο είναι σοφή επιλογή και αποδοτική τεχνική. Διευκολύνει τόσο τη σχεδίαση των γλωσ­σών όσο και την υλοποίηση γλωσσικών συστημάτων, ενώ συμβάλλει και στη σχεδί­αση πιο ευανάγνωστων γλωσσών. Παλαιότερα, υπήρχαν γλώσσες προγραμματισμού στις οποίες τα δύο επίπεδα δόμησης ήταν δυσδιάκριτα. Κάποιες πρώιμες γλώσσες (λ.χ. κάποιες διάλεκτοι της Fortran και της Algol) επέτρεπαν τα διάκενα οπουδήπο­τε − ακόμα και στο μέσον μιας ονομασίας ή ενός κλειδωνυμίου. Άλλες γλώσσες (λ.χ. κάποιες διάλεκτοι της Fortran και της PL/I) επέτρεπαν κλειδωνύμια και μεταβλητές να ταυτίζονται. Αυτά τα χαρακτηριστικά δυσχεραίνουν σημαντικά τη μετάφραση των παραπάνω γλωσσών, αφού η λεκτική δομή δεν είναι σαφώς διαχωρισμένη από τη φραστική.

Όσον αφορά παλαιότερες γλώσσες, αξίζει να περιγράψουμε μια όψη της λεκτικής δομής που έχει πλέον ιστορικό χαρακτήρα. Οι σύγχρονες γλώσσες χειρίζονται τους γραμμοληκτικούς χαρακτήρες σαν κενό χώρο. Αυτοί οι χαρακτήρες δεν έχουν πια πε­ρισσότερη σημασία απ’ ό,τι τα διάκενα ή οι στηλοθέτες. Θα ήταν μάλιστα δυνατόν να απαλειφθούν εντελώς από ένα αρχείο προγράμματος (οπότε το αρχείο θα μετατρε­

2.6 − Η ΛΕΚΤΙΚΗ ΚΑΙ Η ΦΡΑΣΤΙΚΗ ΔΟΜΗ ΜΙΑΣ ΓΛΩΣΣΑΣ 19

Page 42: Συγχρονες γλωσσες προγραμματισμού

πόταν σε μια πολύ μακριά γραμμή κειμένου), χωρίς κανένα πρόβλημα − εκτός βέβαια από τον πονοκέφαλο που θα προκαλούσε η προσπάθεια ανάγνωσης ενός τέτοιου κειμένου.

Αφού οι γραμμοληκτικοί χαρακτήρες δεν έχουν ιδιαίτερη σημασία, καταλαβαί­νετε πως ούτε και οι αύξοντες αριθμοί των στηλών έχουν καμιά ιδιαίτερη σημασία. Για τις περισσότερες σύγχρονες γλώσσες, το εάν κάποιος χαρακτήρας εμφανίζεται στην έκτη ή στην έβδομη «στήλη» είναι αδιάφορο. Και όμως, σε κάποιες παλαιό­τερες γλώσσες οι αριθμοί στηλών είχαν ιδιαίτερη σημασία. Την εποχή των διάτρη­των καρτών υπήρξαν γλώσσες ιδιαίτερα δημοφιλείς οι οποίες είχαν λεκτική δομή προκαθορισμένης μορφοποίησης, δηλαδή υπήρχαν κάποιες στήλες σε κάθε γραμμή κειμένου που είχαν ιδιαίτερη σημασία. Στις πρώιμες διαλέκτους της Fortran, λ.χ., επιτρεπόταν μία εντολή ανά κάρτα («ανά γραμμή», θα γράφαμε σήμερα), και οι πρώ­τες στήλες προορίζονταν για την ενδεχόμενη αριθμητική επιγραφή της αντίστοιχης εντολής. Η Cobol χρησιμοποιούσε επίσης προκαθορισμένη μορφοποίηση, όπως και η Basic. Οι πρώτες γλώσσες που εγκατέλειψαν αυτή την ιδιαίτερη αντιμετώπιση των στηλών μιας γραμμής διαφημίστηκαν ως ελεύθερης μορφοποίησης. Στην εποχή μας όλες σχεδόν οι γλώσσες προγραμματισμού είναι ελεύθερης μορφοποίησης (ακόμα και οι σύγχρονες διάλεκτοι της Fortran, της Cobol και της Basic), και κατά συνέπεια πολύ λίγοι κάνουν πια αυτή τη διάκριση.

2.7. Άλλες μορφές γραμματικής

Υπάρχουν πολλοί διαφορετικοί τρόποι για να περιγράψουμε μια γραμματική. Στηρί­ζονται όλοι στις ίδιες ιδέες μεν, αλλά χρησιμοποιούν διαφορετικούς συμβολισμούς. Σε αυτήν την ενότητα θα περιγράψουμε ορισμένους εναλλακτικούς συμβολισμούς για την καταγραφή μιας γραμματικής.

Μορφή BNΗ μορφή BN έχει ποικίλες παραλλαγές. Κάποιοι σχεδιαστές γραμματικών χρησι­μοποιούν το σύμβολο = (ίσον) ή το → (βέλος), αντί του ::= («παράγει»). Άλλοι χρησιμοποιούν μια διακεκριμένη γραμματοσειρά για να υποδηλώσουν τα τερματικά σύμβολα, όπως κάναμε και εμείς στα παραδείγματά μας. Άλλοι πάλι, δεν χρησιμο­ποιούν γωνιώδεις παρενθέσεις, αλλά επαφίενται επίσης στη γραμματοσειρά για να υποδηλώσουν τη διαφορά ανάμεσα σε λεξιμόρια και παραγωγικά σύμβολα. Ορισμέ­νοι περικλείουν τα λεξιμόρια σε απλά εισαγωγικά. Αυτή είναι μια εξυπηρετική τακτι­κή όταν το λεξιμόριο τυχαίνει να συμπίπτει με έναν από τους ειδικούς χαρακτήρες της μορφής ΒΝ <, >, |, ή ::=. (Αυτοί οι χαρακτήρες αποκαλούνται μετασύμβολα. είναι μέρος της ορίζουσας γλώσσας και όχι της οριζόμενης.)

Μορφή EBNΗ προσθήκη λίγων ακόμη μετασυμβόλων στη μορφή ΒΝ μας επιτρέπει να ορίσουμε εύκολα ορισμένα συντακτικά μορφώματα που απαντούν συχνά στις γλώσσες προ­

20 ΚΕΦΑΛΑΙΟ 2 − Ο ΟΡΙΣΜΟΣ ΤΩΝ ΣΥΝΤΑΚΤΙΚΩΝ ΚΑΝΟΝΩΝ

Page 43: Συγχρονες γλωσσες προγραμματισμού

γραμματισμού. Π.χ. κατά περίπτωση έχουν χρησιμοποιηθεί τα σύμβολα[, ], {, }, (, και ) ως εξής :

■ Η μορφή [φράση] στο δεξιό μέρος ενός κανόνα παραγωγής σημαίνει ότι η συμπερίληψη του κειμένου φράση είναι προαιρετική.

■ Η μορφή {φράση} στο δεξιό μέρος ενός κανόνα παραγωγής σημαίνει ότι το κείμενο φράση είναι δυνατόν να εμφανιστεί οσεσδήποτε φορές − ή και κα­μία.

■ Οι κοινές παρενθέσεις χρησιμοποιούνται για την ομαδοποίηση γλωσσικών όρων στο δεξιό μέρος ενός κανόνα παραγωγής, έτσι ώστε τα σύμβολα |, [], και {} να είναι δυνατόν να χρησιμοποιηθούν χωρίς να προκαλούνται αμφιση­μίες.

Με τη χρήση αυτών των μετασυμβόλων είναι δυνατόν να ορίσουμε κάποια συντα­κτικά σχήματα με πιο απλό τρόπο απ’ ό,τι στη μορφή ΒΝ. Για παράδειγμα, μια εντολή if­then με εναλλακτικό τμήμα else είναι δυνατόν να οριστεί ως εξής:

<υποθετική εντολή> ::= if <έκφραση> then <εντολή> [ else <εντολή> ]

Υπενθυμίζουμε ότι οι αγκύλες δεν είναι τμήμα της οριζόμενης γλώσσας, αλλά μετα­σύμβολα που δηλώνουν ότι η φράση else <εντολή> είναι προαιρετική.

Μια ακολουθία από μηδέν ή περισσότερες εντολές οι οποίες διαχωρίζονται μετα­ξύ τους από μια αγγλική άνω τελεία θα μπορούσε να ορίζεται ως εξής:

<ακολουθία εντολών> ::= { <εντολή> ; }

Και πάλι τα άγκιστρα δεν αποτελούν τμήμα της οριζόμενης γλώσσας. Είναι μετα­σύμβολα που δηλώνουν ότι η <εντολή> είναι δυνατόν να επαναληφθεί μηδέν ή πε­ρισσότερες φορές. Μια ακολουθία από μηδέν ή περισσότερους όρους καθένας από τους οποίους είναι είτε μια δήλωση είτε μια εντολή, και οι οποίοι διαχωρίζονται με­ταξύ τους από μια αγγλική άνω τελεία θα μπορούσε να ορίζεται ως εξής:

<ακολουθία όρων> ::= { (<εντολή> | <δήλωση>) ; }

Και εδώ οι παρενθέσεις είναι μετασύμβολα: δηλώνουν ότι το οριοθετικό σύμβολο ; δεν είναι μέρος της επιλογής που δηλώνεται με το μετασύμβολο |.

Αν και η απλή μορφή ΒΝ μιας γραμματικής αρκεί για να περιγράψει όλα τα παρα­πάνω συντακτικά σχήματα, η χρήση των μετασυμβόλων που περιγράψαμε καθιστά τους σχετικούς κανόνες πιο ευανάγνωστους. Όπως και το μετασύμβολο | της απλής μορφής ΒΝ, τα μετασύμβολα [, ], {, }, ( και ) μας επιτρέπουν να περιγράψουμε ένα σύνολο κανόνων παραγωγής πολύ πιο ευσύνοπτα.

Κάθε προσθήκη τέτοιων στοιχείων στην απλή μορφή ΒΝ δημιουργεί μια επεκτε‑ταμένη μορφή ΒΝ (μορφή ΕΒΝ), και κατά καιρούς έχουν χρησιμοποιηθεί πολλές τέτοιες παραλλαγές της μορφής ΒΝ. Παραθέτουμε στη συνέχεια ένα απόσπασμα από τον ορισμό της Java. Αν και ο συμβολισμός διαφέρει αρκετά, οι ομοιότητες με τη μορφή ΕΒΝ είναι αναγνωρίσιμες. Ο δείκτης opt, ειδικότερα, παίζει τον ρόλο των αγκυλών [, ], υποδηλώνοντας ένα προαιρετικό μέρος της γλώσσας.

2.7 − ΑΛΛΕΣ ΜΟΡΦΕΣ ΓΡΑΜΜΑΤΙΚΗΣ 21

Η προεπισκόπηση των επόμενων σελίδων δεν είναι διαθέσιμη