diff options
Diffstat (limited to 'el-gr')
| -rw-r--r-- | el-gr/css-gr.html.markdown | 242 | ||||
| -rw-r--r-- | el-gr/java-gr.html.markdown | 858 | ||||
| -rw-r--r-- | el-gr/racket-gr.html.markdown | 745 | ||||
| -rw-r--r-- | el-gr/scala-gr.html.markdown | 689 | 
4 files changed, 2534 insertions, 0 deletions
| diff --git a/el-gr/css-gr.html.markdown b/el-gr/css-gr.html.markdown new file mode 100644 index 00000000..31b30479 --- /dev/null +++ b/el-gr/css-gr.html.markdown @@ -0,0 +1,242 @@ +--- +language: css +contributors: +    - ["Kostas Bariotis", "http://kostasbariotis.com"] +filename: css-gr.html.markdown +lang: el-gr +--- + +Η αρχική μορφή του Παγκόσμιου Ιστού αποτελείτο απο καθαρό κείμενο, χωρίς οπτικά αντικείμενα. Με το πέρας  +του χρόνου και την εξέλιξη των Φυλλομετρητών, οι πλούσιες σελίδες, σε οπτικά και πολυμεσικά αντικείμενα,  +έγιναν καθημερινότητα. + +Η CSS μας βοηθάει να διαχωρήσουμε το περιεχόμενο της σελίδας μας (HTML) απο την οπτική της περιγραφή. + +Με την CSS ορίζουμε οπτικές ιδιότητες (χρώμα, μέγεθος, κλπ) σε HTML αντικείμενα (H1, div, κλπ). + +```css +/* Τα σχόλια εμφανίζονται εντός καθέτου-αστερίσκου, όπως εδώ.  +   Δεν υπάρχουν σχόλια μια γραμμής και πολλών. */ + +/* #################### +   ## ΚΑΝΟΝΕΣ +   #################### */ + +/* ένας κανόνας χρησιμοποιείται για να στοχεύσουμε ένα αντικείμενο (selector). */ +selector { property: value; /* περισσότερες ιδιότητες...*/ } + +/* +Αυτό είναι ενα παράδειγμα αντικειμένου +<div class='class1 class2' id='anID' attr='value' otherAttr='en-us foo bar' /> +*/ + +/* Μπορούμε να το στοχεύσουμε με την χρήση CSS κλάσεων */ +.class1 { } + +/* Ή και με τις δύο κλάσεις! */ +.class1.class2 { } + +/* Και με το όνομα του */ +div { } + +/* Ή με το id του */ +#anID { } + +/* Ή με το γεγονός ότι περιέχει ενα attribute */ +[attr] { font-size:smaller; } + +/* Ή οτι το attribute αυτό έχει μια συγκεκριμένη τιμή */ +[attr='value'] { font-size:smaller; } + +/* Ξεκινάει απο το λεκτικό (CSS 3) */ +[attr^='val'] { font-size:smaller; } + +/* Καταλήγει σε αυτο το λεκτικό (CSS 3) */ +[attr$='ue'] { font-size:smaller; } + +/* Περιέχει κάποιο λεκτικό */ +[otherAttr~='foo'] { } +[otherAttr~='bar'] { } + +/* περιέχει το λεκτικό σε λίστα χωρισμένη με παύλες, δηλαδή: "-" (U+002D) */ +[otherAttr|='en'] { font-size:smaller; } + + +/* Μπορούμε να προσθέσουμε μεταξύ τους selectors για να δημιουργήσουμε πιο αυστηρούς.  +  Δεν βάζουμε κενά ανάμεσα. */ +div.some-class[attr$='ue'] { } + +/* Μπορούμε να επιλέξουμε αντικείμενα που βρίσκονται μέσα σε άλλα. */ +div.some-parent > .class-name { } + +/* Ή κάποιο αντικείμενο απόγονο ανεξαρτήτου του βάθους της σχέσης τους. */ +div.some-parent .class-name { } + +/* ΠΡΟΣΟΧΗ: ο ίδιος selector χωρίς κενά έχει άλλο νόημα. (Άσκηση προς τον αναγνώστη) */ +div.some-parent.class-name { } + +/* Μπορούμε να επιλέξουμε αντικείμενα με βάση το αμέσως επόμενο αντικείμενο στο ίδιο επίπεδο. */ +.i-am-just-before + .this-element { } + +/* Ή οποιοδήποτε αντικείμενο που προηγείται */ +.i-am-any-element-before ~ .this-element { } + +/* Με την βοήθεια των ψευδο-κλάσεων μπορούμε να επιλέξουμε αντικείμενα που βρίσκονται σε μια  +  ορισμένη κατάασταση. */ + +/* π.χ. όταν ο κέρσορας είναι πάνω απο ένα αντικείμενο */ +selector:hover { } + +/* ή ένας υπερσύνδεσμος που πατήθηκε */ +selector:visited { } + +/* ή που δεν πατήθηκε */ +selected:link { } + +/* ή ένα αντικείμενο που επιλέχθηκε */ +selected:focus { } + +/* οποιοδήποτε αντικείμενο είναι το πρώτο παιδί των γονέων του */ +selector:first-child {} + +/* οποιοδήποτε αντικείμενο είναι το πρώτοτελευταίο παιδί των γονέων του */ +selector:last-child {} + +/* Όπως και με τις ψευδο-κλάσεις, τα ψευδο-αντικείμενα μας επιτρέπουν τα τροποοιήσουμε συγκεκριμένα  +  κομμάτια της σελίδας */ + +/* επιλέγει το ψευδο-αντικείμενο ακριβώς πριν απο το αντικείμενο */ +selector::before {} + +/* επιλέγει το ψευδο-αντικείμενο ακριβώς μετά απο τον αντικείμενο */ +selector::after {} + +/* Σε σωστά σημεία (όχι πολύ ψηλά στην ιεραρχία) ο αστερίσκος μπορείς να χρησιμοποιηθεί για να  +  επιλέξουμε όλα τα αντικείμενα */ +* { } /* όλα τα αντικείμενα της σελίδας */ +.parent * { } /* όλους τους απόγονους */ +.parent > * { } /* όλους τους απόγονους πρώτου επιπέδου */ + +/* #################### +   ## Ιδιότητες +   #################### */ + +selector { +     +    /* Οι μονάδες μπορούν να είναι είτε απόλυτες είτε σχετικές */ +     +    /* Σχετικές μονάδες */ +    width: 50%;       /* ποσοστό επί του πλάτους του γονέα */ +    font-size: 2em;   /* πολλαπλασιαστής της αρχικής τιμής του αντικειμένου */ +    font-size: 2rem;  /* ή της τιμής του πρώτου αντικειμένου στην ιεραρχία */ +    font-size: 2vw;   /* πολλαπλαστιαστής του 1% του οπτικού πλάτους */ +    font-size: 2vh;   /* ή τους ύψους */ +    font-size: 2vmin; /* οποιοδήποτε απο αυτα τα δύο είναι το μικρότερο */ +    font-size: 2vmax; /* ή το μεγαλύτερο */ +     +    /* Απόλυτες μονάδες */ +    width: 200px;     /* pixels */ +    font-size: 20pt;  /* στιγμες */ +    width: 5cm;       /* εκατοστά */ +    min-width: 50mm;  /* χιλιοστά */ +    max-width: 5in;   /* ίντσες */ +     +    /* Χρώματα */ +    color: #F6E;                 /* σύντομη δεκαεξαδική μορφή */ +    color: #FF66EE;              /* δεκαεξαδική μορφή */ +    color: tomato;               /* χρώμα με το όνομα του (συγκεκριμένα χρώματα) */ +    color: rgb(255, 255, 255);   /* τιμή RGB */ +    color: rgb(10%, 20%, 50%);   /* τιμή RGB με ποσοστά */ +    color: rgba(255, 0, 0, 0.3); /* τιμή RGBA (CSS3) σσ. 0 < a < 1 */ +    color: transparent;          /* όπως και το παραπάνω με a = 0 */ +    color: hsl(0, 100%, 50%);    /* τιμή hsl με ποσοστά (CSS 3) */ +    color: hsla(0, 100%, 50%, 0.3); /* τιμή hsla με ποσοστά και a */ +     +    /* Εικόνες μπορούν να τοποθετηθούν στον φόντο ενός αντικειμένου */ +    background-image: url(/img-path/img.jpg); +     +    /* Γραμματοσειρές */ +    font-family: Arial; +    /* εάν η γραμματοσειρα περιέχει κενά */ +    font-family: "Courier New"; +    /* εάν η πρώτη γραμματοσειρα δε βρεθεί εγκατεστημένη στο Λειτουργικό Σύστυμα, αυτόματα  +      επιλέγετε η δεύτερη, κ.κ.ε. */ +    font-family: "Courier New", Trebuchet, Arial, sans-serif; +} +``` + +## Χρήση + +Αποθηκεύουμε ένα αρχείο CSS με την επέκταση `.css`. + +```xml +<!-- Πρέπει να συμπεριλάβουμε το αρχείο στην επικεφαλίδα(head) ενος HTML αρχείου. +  σσ. http://stackoverflow.com/questions/8284365 --> +<link rel='stylesheet' type='text/css' href='path/to/style.css' /> + +<!-- Μπορούμε να το ενσωματώσουμε --> +<style> +   a { color: purple; } +</style> + +<!-- Ή απευθείας σε κάποιο αντικείμενο (inline) --> +<div style="border: 1px solid red;"> +</div> +``` + +## Ειδικότητα των κανόνων (Cascading απο το αγγλικό τίτλο Cascading Style Sheets) + +Ένα αντικείμενο μπορεί να στοχευθεί απο πολλούς κανόνες και μπορεί η ίδια ιδιότητα να  +περιλαμβάνετε σε πολλούς κανόνες. Σε αυτές της περιπτώσεις υπερισχύει πάντα ο πιο ειδικός  +κανόνας και απο αυτούς, αυτός που εμφανίζεται τελευταίος. + +```css +/* A */ +p.class1[attr='value'] + +/* B */ +p.class1 { } + +/* C */ +p.class2 { } + +/* D */ +p { } + +/* E */ +p { property: value !important; } +``` + +```xml +<p style='/*F*/ property:value;' class='class1 class2' attr='value' /> +``` + +Η σειρά θα είναι: + +* `E` έχει μεγαλύτερο βάρος λόγω του `!important`. Κάλες πρακτικές λένε να το αποφεύγουμε. +* `F` επόμενο λόγω του inline κανόνα. +* `A` επόμενο λόγω του το οτι είναι πιο ειδικό. Περιέχει τρεις selectors. +* `C` επόμενο, λόγω του οτι εμφανίζεται μετα το Β και ας έχει την ίδια ειδικότητα. +* `B` επόμενο. +* `D` τελευταίο. + +## Συμβατότητα + +Τα περισσότερα απο τα παραπάνω ήδη υποστηρίζονται απο τους γνωστούς φυλλομετρητές. Άλλα θα πρέπει  +πάντα να ελέγχουμε πρωτου τους χρησιμοποιήσουμε. + +## Περισσότερα + +* Έλεγχος συμβατότητας, [CanIUse](http://caniuse.com). +* CSS Playground [Dabblet](http://dabblet.com/). +* [Mozilla Developer Network's CSS documentation](https://developer.mozilla.org/en-US/docs/Web/CSS) +* [Codrops' CSS Reference](http://tympanus.net/codrops/css_reference/) + +## Μελέτη + +* [Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/) +* [Selecting elements using attributes](https://css-tricks.com/almanac/selectors/a/attribute/) +* [QuirksMode CSS](http://www.quirksmode.org/css/) +* [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context) +* [SASS](http://sass-lang.com/) and [LESS](http://lesscss.org/) for CSS pre-processing +* [CSS-Tricks](https://css-tricks.com) diff --git a/el-gr/java-gr.html.markdown b/el-gr/java-gr.html.markdown new file mode 100644 index 00000000..5dad4a60 --- /dev/null +++ b/el-gr/java-gr.html.markdown @@ -0,0 +1,858 @@ +--- +language: java +contributors: +    - ["Jake Prather", "http://github.com/JakeHP"] +    - ["Jakukyo Friel", "http://weakish.github.io"] +    - ["Madison Dickson", "http://github.com/mix3d"] +    - ["Simon Morgan", "http://sjm.io/"] +    - ["Zachary Ferguson", "http://github.com/zfergus2"] +    - ["Cameron Schermerhorn", "http://github.com/cschermerhorn"] +    - ["Rachel Stiyer", "https://github.com/rstiyer"] +filename: LearnJava-gr.java +translators: +  - ["Andreas Loizou" , "https://github.com/lack3r/"] +lang: el-gr +--- + +H Java είναι μία γενικού-σκοπού, συντρέχων (concurrent), βασισμένη σε κλάσεις,  +αντικειμενοστρεφής (object oriented) γλώσσα προγραμματισμού. +[Διαβάστε περισσότερα εδώ.](http://docs.oracle.com/javase/tutorial/java/) + +```java +// Τα σχόλια μονής γραμμής ξεκινούν με // +/* +Τα σχόλια πολλών γραμμών μοιάζουν κάπως έτσι. +*/ +/** +Τα σχόλια JavaDoc μοιάζουν κάπως έτσι. Χρησιμοποιούνται για να περιγράψουν την  +Κλάση ή διάφορα χαρακτηριστικά της Κλάσης. +*/ + +// Εισαγωγή της κλάσης ArrayList η οποία βρίσκεται εντός του πακέτου java.util +import java.util.ArrayList; +// Εισαγωγή όλων των κλάσεων που βρίσκονται εντός του πακέτου java.security +import java.security.*; + +// Κάθε αρχείο .java περιέχει μία δημόσια(public) κλάση εξωτερικού-επιπέδου  +// (outer-level), η οποία έχει το ίδιο ονομα με το αρχείο. +public class LearnJava { + +    // Για να τρέξει ένα πρόγραμμα java, πρέπει να έχει μία κύρια μέθοδο (main  +    // method) ως αρχικό σημείο. +    public static void main (String[] args) { + +        // Χρησιμοποιούμε τη μέθοδο System.out.println() για να τυπώσουμε  +        // γραμμές. +        System.out.println("Hello World!"); +        System.out.println( +            "Integer: " + 10 + +            " Double: " + 3.14 + +            " Boolean: " + true); + +        // Για να τυπώσουμε χωρίς να τυπωθεί αλλαγή γραμμής (newline),  +        // χρησιμοποιούμε System.out.print(). +        System.out.print("Hello "); +        System.out.print("World"); + +        // Χρησιμοποιούμε τη μέθοδο System.out.printf() για έυκολη μορφοποίηση  +        // της εκτύπωσης. +        System.out.printf("pi = %.5f", Math.PI); // => pi = 3.14159 + +        /////////////////////////////////////// +        // Μεταβλητές(Variables) +        /////////////////////////////////////// + +        /* +        *  Δήλωση Μεταβλητών +        */ +        // Δηλώνουμε μία μεταβλητή χρησιμοποιώντας τη μορφή  +        // <Τύπος Μεταβλητής> <Όνομα Μεταβλητής> +        int fooInt; +        // Δηλώνουμε πολλαπλές μεταβλητές ίδιου τύπου χρησιμοποιώντας τη μορφή  +        // <Τύπος> <Όνομα1>, <Όνομα2>, <Όνομα3> +        int fooInt1, fooInt2, fooInt3; + +        /* +        *  Αρχικοποίηση Μεταβλητών +        */ + +        // Αρχικοποιούμε μια μεταβλητή χρησιμοποιώντας τη μορφή  +        // <τύπος> <όνομα> = <τιμή> +        int fooInt = 1; +        // Αρχικοποιούμε πολλαπλές μεταβλητές ιδίου τύπου με την ίδια τιμή  +        // χρησιμοποιώντας <τύπος> <Όνομα1>, <Όνομα2>, <Όνομα3> = <τιμή> +        int fooInt1, fooInt2, fooInt3; +        fooInt1 = fooInt2 = fooInt3 = 1; + +        /* +        *  Τύποι μεταβλητών +        */ +        // Byte - 8-bit signed two's complement integer +        // (-128 <= byte <= 127) +        byte fooByte = 100; + +        // Short - 16-bit signed two's complement integer +        // (-32,768 <= short <= 32,767) +        short fooShort = 10000; + +        // Integer - 32-bit signed two's complement integer +        // (-2,147,483,648 <= int <= 2,147,483,647) +        int fooInt = 1; + +        // Long - 64-bit signed two's complement integer +        // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) +        long fooLong = 100000L; +        // Το L χρησιμοποιείται για να δηλώσει ότι η συγκεκριμένη τιμή της  +        // μεταβλητής είναι τύπου Long; +        // Ό,τιδήποτε χρησιμοποιείται χωρίς αυτό τυχαίνει μεταχείρισης όπως  +        // μία τιμή μεταβλητής integer by default. + +        // Σημείωση: Η Java δεν έχει unsigned τύπους. + +        // Float - Single-precision 32-bit IEEE 754 Floating Point +        // 2^-149 <= float <= (2-2^-23) * 2^127  +        float fooFloat = 234.5f; +        // f or F χρησιμοποιείται για να δηλώσει ότι η συγκεκριμένη τιμή  +        // μεταβλητής είναι τύπου float; +        // αλλιώς τυγχαίνει μεταχείρισης όπως μία τιμή μεταβλητής double. + +        // Double - Double-precision 64-bit IEEE 754 Floating Point +        // 2^-1074 <= x <= (2-2^-52) * 2^1023 +        double fooDouble = 123.4; + +        // Boolean - Αληθής και Ψευδής (true & false) +        boolean fooBoolean = true; +        boolean barBoolean = false; + +        // Char - Ένας μόνο χαρακτήρας 16-bit Unicode +        char fooChar = 'A'; + +        // Οι μεταβλητές final δεν μπορούν να πάρουν άλλη τιμή  +        // μετά την αρχικοποίηση τους, +        final int HOURS_I_WORK_PER_WEEK = 9001; +        // αλλά μπορούν να αρχικοποιηθούν αργότερα. +        final double E; +        E = 2.71828; + + +        // BigInteger - Immutable αυθαίρετης-ακρίβειας ακέραιος +        // +        // Ο BigInteger είναι ένας τύπος δεδομένων ο οποίος επιτρέπει στους  +        // προγραμματιστές να χειρίζονται ακέραιους μεγαλύτερους από 64-bits.  +        // Οι ακέραιοι αποθηκεύονται ως πίνακας από bytes και τυχαίνουν  +        // επεξεργασίας χρησιμοποιώντας συναρτήσεις εσωματωμένες στην κλάση  +        // BigInteger +        // Ένας BigInteger μπορεί να αρχικοποιηθεί χρησιμοποιώντας ένα πίνακα  +        // από bytes ή γραμματοσειρά (string). +         +        BigInteger fooBigInteger = new BigInteger(fooByteArray); + + +        // BigDecimal - Immutable, αυθαίρετης-ακρίβειας, εμπρόσημος (signed) +        // δεκαδικός αριθμός +        // +        // Ένας BigDecimal παίρνει δύο μέρη: Μία αυθαίρετης ακρίβειας,  +        // ακέραια, unscaled τιμή και μία κλιμάκωση(scale) ως ένα 32-bit  +        // ακέραιο (integer). +        // +        // Ο BigDecimal επιτρέπει στον προγραμματιστή να έχει πλήρη έλεγχο  +        // όσον αφορά τη δεκαδική στρογγυλοποίηση (rounding). Προτείνεται η  +        // χρήση του BigDecimal με τιμές νομισμάτων και όπου απαιτείται η  +        // ακριβής δεκαδική ακρίβεια. +        // +        // Ο BigDecimal μπορεί να αρχικοποιηθεί με int, long, double ή String +        // ή με την αρχικοποίηση της unscaled τιμής (BigInteger) και της  +        // κλίμακας (scale) (int). + +        BigDecimal fooBigDecimal = new BigDecimal(fooBigInteger, fooInt); +         +        // Χρειάζεται να είμαστε προσεκτικοί με τον κατασκευαστή (constructor)  +        // ο οποίος παίρνει float ή double καθώς η ανακρίβεια του float/double  +        // θα αντιγραφεί στον BigDecimal. +        // Είναι προτιμότερο να χρησιμοποιείται ο κατασκευαστής String (String  +        // constructor) όταν χρειάζεται ακριβής τιμή. +         +        BigDecimal tenCents = new BigDecimal("0.1"); + +        // Strings - Γραμματοσειρές +        String fooString = "My String Is Here!"; + +        // Ο χαρακτήρας \n είναι ένας χαρακτήρας διαφυγής (escaped character)  +        // ο οποίος ξεκινά μία νέα γραμμή +        String barString = "Printing on a new line?\nNo Problem!"; +        // Ο χαρακτήρας \t είναι ένας χαρακτήρας διαφυγής (escaped character) +        // ο οποίος προσθέτει ένα χαρακτήρα tab +        String bazString = "Do you want to add a tab?\tNo Problem!"; +        System.out.println(fooString); +        System.out.println(barString); +        System.out.println(bazString); + +        // Πίνακες (Arrays) +        // Το μέγεθος του πίνακα πρέπει να αποφασιστεί με την αρχικοποίηση του +        // πίνακα +        // Οι ακόλουθες μορφές μπορούν να χρησιμοποιηθούν για την δήλωση ενός  +        // πίνακα  +        // <Τυπος δεδομένων>[] <Όνομα Μεταβλητής> = new <Τύπος Δεδομένων>[<μέγεθος πίνακα>]; +        // <Τυπος δεδομένων> <Όνομα Μεταβλητής>[] = new <Τυπος δεδομένων>[<μέγεθος πίνακα>]; +        int[] intArray = new int[10]; +        String[] stringArray = new String[1]; +        boolean boolArray[] = new boolean[100]; + +        // Ακόμη ένας τρόπος για να δηλώσεις (to declare) και να  +        // αρχικοποιήσεις ένα πίνακα +        int[] y = {9000, 1000, 1337}; +        String names[] = {"Bob", "John", "Fred", "Juan Pedro"}; +        boolean bools[] = new boolean[] {true, false, false}; + +        // Ευρετηρίαση (indexing) ενός πίνακα - Πρόσβαση (accessing) ενός  +        // στοιχείου +        System.out.println("intArray @ 0: " + intArray[0]); + +        // Οι πίνακες ξεκινούν από το μηδέν (zero-indexed) και είναι ευμετάβλητοι (mutable). +        intArray[1] = 1; +        System.out.println("intArray @ 1: " + intArray[1]); // => 1 + +        // Παρόμοια +        // ArrayLists - Παρόμοιοι με τους πίνακες με τη διαφορά ότι προσφέρουν  +        // περισσότερη λειτουργικότητα και το μέγεθος είναι ευμετάβλητο  +        // (mutable). +        // LinkedLists - Υλοποίηση διπλά-συνδεδεμένης λίστας(doubly-linked  +        // list). Όλες οι λειτουργίες εκτελώνται όπως αναμένεται σε μία διπλά  +        // συνδεδεμένη (doubly-linked) λίστα. +        // Maps - Ένα σύνολο αντικειμένων τα οποία συνδέου (map) κλειδιά (keys) +        // σε τιμές (values). Ο Map είναι διεπαφή (interface) και συνεπώς δεν  +        // μπορεί να συγκεκριμενοποίηθεί (instantiated). +        // Ο τύπος των κλειδιών και των τιμών τα οποία συμπεριλαμβάνονται σε  +        // ένα Map πρέπει να καθοριστεί κατά τη διάρκεια της  +        // συγκεκριμενοποίησης (instantiation) της κλάσης που υλοποιεί τη  +        // διεπαφή Map. Κάθε κλειδί (key) μπορεί να συνδεθεί (map) σε μόνο μία  +        // αντίστοιχη τιμή και κάθε κλειδί μπορεί να εμφανιστεί μόνο μία φορά  +        // (no duplicates). +        // HashMaps - Η κλάση αυτή χρησιμοποιεί ένα πίνακα-κατακερματισμού  +        // (hashtable) για να υλοποιήσει τη διεπαφή Map. Αυτό επιτρέπει το  +        // χρόνο εκτέλεσης βασικών λειτουργιών, όπως της get και insert  +        // στοιχείου να παραμείνει σταθερός (constant) ακόμη και για μεγάλα  +        // σύνολα (sets.) + + +        /////////////////////////////////////// +        // Τελεστές (Operators) +        /////////////////////////////////////// +        System.out.println("\n->Operators"); + +        int i1 = 1, i2 = 2; // Συντομογραφία για πολλαπλές δηλώσεις + +        // Οι αριθμητικοί τελεστές είναι απλοί +        System.out.println("1+2 = " + (i1 + i2)); // => 3 +        System.out.println("2-1 = " + (i2 - i1)); // => 1 +        System.out.println("2*1 = " + (i2 * i1)); // => 2 +        System.out.println("1/2 = " + (i1 / i2)); // => 0 (int/int returns int) +        System.out.println("1/2 = " + (i1 / (double)i2)); // => 0.5 + +        // Υπόλοιπο (Modulo) +        System.out.println("11%3 = "+(11 % 3)); // => 2 + +        // Τελεστές σύγκρισης +        System.out.println("3 == 2? " + (3 == 2)); // => false +        System.out.println("3 != 2? " + (3 != 2)); // => true +        System.out.println("3 > 2? " + (3 > 2)); // => true +        System.out.println("3 < 2? " + (3 < 2)); // => false +        System.out.println("2 <= 2? " + (2 <= 2)); // => true +        System.out.println("2 >= 2? " + (2 >= 2)); // => true + +        // Λογικοί Τελεστές (Boolean) +        System.out.println("3 > 2 && 2 > 3? " + ((3 > 2) && (2 > 3))); // => false +        System.out.println("3 > 2 || 2 > 3? " + ((3 > 2) || (2 > 3))); // => true +        System.out.println("!(3 == 2)? " + (!(3 == 2))); // => true + +        // Τελεστές πράξεων με bits (Bitwise)! +        /* +        ~      bitwise τελεστής μοναδιαίου συμπληρώματος (Unary bitwise complement) +        <<     Προσημασμένη ολίσθηση αριστερά (Signed left shift) +        >>     Προσημασμένη/Αριθμητική ολίσθηση Δεξιά (Signed/Arithmetic right shift) +        >>>    Μη προσημασμένη/Λογική ολίσθηση δεξιά (Unsigned/Logical right shift) +        &      Διαδικός τελεστής AND (Bitwise AND) +        ^      Διαδικός τελεστής XOR (Bitwise exclusive OR) +        |      Διαδικός τελεστής OR (Bitwise inclusive OR) +        */ + +        // Αυξητικοί τελεστές +        int i = 0; +        System.out.println("\n->Inc/Dec-rementation"); +        // Οι τελεστές ++ και -- μειώνουν και αυξάνουν κατά 1 αντίστοιχα. +        // Εάν τοποθετητούν πριν τη μεταβλητή, αυξάνουν και μετά επιστρέφουν. +        // Μετά τη μεταβλητή επιστρέφουν και μετά αυξάνουν. +        System.out.println(i++); // i = 1, τυπώνει 0 (post-increment) +        System.out.println(++i); // i = 2, τυπώνει 2 (pre-increment) +        System.out.println(i--); // i = 1, τυπώνει 2 (post-decrement) +        System.out.println(--i); // i = 0, τυπώνει 0 (pre-decrement) + +        /////////////////////////////////////// +        // Δομές ελέγχου (Control Structures) +        /////////////////////////////////////// +        System.out.println("\n->Control Structures"); + +        // Οι δηλώσεις If είναι c-like +        int j = 10; +        if (j == 10) { +            System.out.println("I get printed"); +        } else if (j > 10) { +            System.out.println("I don't"); +        } else { +            System.out.println("I also don't"); +        } + +        // Επανάληψη While (While loop) +        int fooWhile = 0; +        while(fooWhile < 100) { +            System.out.println(fooWhile); +            // Άυξησε τον μετρητή +            // Επανάλαβε 100 φορές, fooWhile 0,1,2...99 +            fooWhile++; +        } +        System.out.println("fooWhile Value: " + fooWhile); + +        // Επανάληψη Do While (Do While Loop) +        int fooDoWhile = 0; +        do { +            System.out.println(fooDoWhile); +            // Άυξησε το μετρητή(counter) +            // Επανάλαβε 99 times, fooDoWhile 0->99 +            fooDoWhile++; +        } while(fooDoWhile < 100); +        System.out.println("fooDoWhile Value: " + fooDoWhile); + +        // Επανάληψη For (For Loop) +        // Δομή επανάληψης for =>  +        // for(<Αρχική Δήλωση>; <προυπόθεση (conditional)>; <βήμα (step)>) +        for (int fooFor = 0; fooFor < 10; fooFor++) { +            System.out.println(fooFor); +            // Iterated 10 times, fooFor 0->9 +        } +        System.out.println("fooFor Value: " + fooFor); +         +        // Έξοδος από εμφωλευμένη (nested) επανάληψη For με ετικέττα (Label) +        outer: +        for (int i = 0; i < 10; i++) { +          for (int j = 0; j < 10; j++) { +            if (i == 5 && j ==5) { +              break outer; +              // δραπετεύει εκτός της εξωτερικής(outer) επανάληψης αντί μόνο της εσωτερικής +            } +          } +        } +         +        // Επανάληψη For Each +        // Η επανάληψη for είναι επίσης ικανή να επαναλαμβάνεται τόσο σε  +        // πίνακες όσο και σε αντικείμενα τα οποία υλοποιούν τη διεπαφή  +        // Iterable. +        int[] fooList = {1, 2, 3, 4, 5, 6, 7, 8, 9}; +        // Σύνταξη της επανάληψης for each => for (<αντικείμενο> : <iterable>) +        // Διαβάζεται ως: Για κάθε αντικείμενο στο iterable +        // Σημείωση: ο τύπος του αντικειμένου πρέπει να τεριάζει με τον τύπο του στοιχείου του iterable. + +        for (int bar : fooList) { +            System.out.println(bar); +            //Επαναλαμβάνεται 9 φορές και τυπώνει 1-9 σε καινούριες γραμμές +        } + +        // Switch Case +        // Ένα switch δουλέυει με byte, short, char, και int τύπους δεδομένων. +        // Δουλέυει επίσης με τύπους enumerated (Συζήτηση στους τύπους Enum),  +        // τη κλάση String, και μερικές ειδικές περιπτώσεις οι οποίες  +        // περιλαμβάνουν primitive τύπους: Character, Byte, Short, and Integer. +        int month = 3; +        String monthString; +        switch (month) { +            case 1: monthString = "January"; +                    break; +            case 2: monthString = "February"; +                    break; +            case 3: monthString = "March"; +                    break; +            default: monthString = "Some other month"; +                     break; +        } +        System.out.println("Switch Case Result: " + monthString); +         +        // Αρχίζοντας από τη Java 7, switching για Strings δουλεύει έτσι: +        String myAnswer = "maybe"; +        switch(myAnswer) { +            case "yes": +                System.out.println("You answered yes."); +                break; +            case "no": +                System.out.println("You answered no."); +                break; +            case "maybe": +                System.out.println("You answered maybe."); +                break; +            default: +                System.out.println("You answered " + myAnswer); +                break; +        } + +        // Συντομογραφία του Conditional +        // Μπορείς να χρησιμοποιήσεις τον τελεστή '?' για γρήγορες αναθέσεις ή  +        // logic forks. Διαβάζεται ως "Αν η (πρόταση) είναι αληθής,  +        // χρησιμοποίησε <την πρώτη τιμή>, αλλιώς, χρησιμοποία <την δεύτερη  +        // τιμή>" +        int foo = 5; +        String bar = (foo < 10) ? "A" : "B"; +        System.out.println(bar); // Prints A, because the statement is true + + +        //////////////////////////////////////// +        // Μετατροπή Τύπων Δεδομένων και Typecasting +        //////////////////////////////////////// + +        // Μετατροπή δεδομένων + +        // Μετατροπή από String σε Integer +        Integer.parseInt("123");//returns an integer version of "123" + +        // Μετατροπή από Integer σε String +        Integer.toString(123);//returns a string version of 123 + +        // Για άλλες μετατροπές δες τις ακόλουθες κλάσεις: +        // Double +        // Long +        // String + +        // Typecasting +        // Μπορείς επίσης να κάνεις cast αντικείμενα Java. Υπάρχουν πολλές  +        // λεπτομέρειες και μερικές πραγματεύονται κάποιες πιο προχωρημένες  +        // ένοιες. Για δες εδώ: +        // http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html + + +        /////////////////////////////////////// +        // Κλάσεις και Συναρτήσεις +        /////////////////////////////////////// + +        System.out.println("\n->Classes & Functions"); + +        // (Ο ορισμός της κλάσης Bicycle ακολουθεί) + +        // Χρησιμοποία το new για να δημιουργήσεις ένα αντικείμενο μίας κλάσης +        Bicycle trek = new Bicycle(); + +        // Κλήση μεθόδων του αντικειμένου +        trek.speedUp(3); // Πάντοτε πρέπει να χρησιμοποιείς μεθόδους setter  +        // και getter +        trek.setCadence(100); + +        // Το toString επιστρέφει την αναπαράσταση σε String μορφή του  +        // αντικειμένου αυτού. +        System.out.println("trek info: " + trek.toString()); + +        // Double Brace Initialization +        // Η Γλώσσα Java δεν έχει σύνταξη για το πως να δημιουργήσεις static  +        // Collections με κάποιο εύκολο τρόπο. Συνήθως θα το κάνεις αυτό με  +        // τον παρακάτω τρόπο: + +        private static final Set<String> COUNTRIES = new HashSet<String>(); +        static { +           validCodes.add("DENMARK"); +           validCodes.add("SWEDEN"); +           validCodes.add("FINLAND"); +        } + +        // Αλλά υπάρχει ένας κομψός τρόπος να επιτύχεις το ίδιο πράγμα +        // ευκολότερα, χρησιμοποιώντας κάτι το οποίο λέγεται Double Brace +        // Initialization. + +        private static final Set<String> COUNTRIES = new HashSet<String>() {{ +            add("DENMARK"); +            add("SWEDEN"); +            add("FINLAND"); +        }} + +        // Η πρώτη αγκύλη δημιουργεί μία νέα AnonymousInnerClass και η +        // δεύτερη δηλώνει ένα instance initializer block. Το block +        // καλείται όταν η ανώνυμη εσωτερική κλάση δημιουργηθεί. +        // Η μέθοδος αύτή δεν δουλεύει μόνο για τις Collections, αλλά για όλες  +        // τις non-final κλάσεις. + +    } // Τέλος μεθόδου main +} // Τέλος κλάσης LearnJava + + +// Μπορείς να κάνεις include άλλες, όχι-δημόσιες (non-public)  +// εξωτερικού-επιπέδου (outer-level) κλάσεις σε ένα αρχείο .java, αλλά δεν  +// είναι καλή πρακτική. Αντί αυτού, διαχώρησε τις κλάσεις σε ξεχωριστά αρχεία. + +// Σύνταξη Δήλωσης Κλάσης (Class Declaration Syntax): +// <public/private/protected> class <class name> { +//    // Συμπεριλαμβάνονται πεδία δεδομένων (data fields), κατασκευαστές (constructors), συναρτήσεις (functions) . +//    // Οι συναρτήσεις ονομάζονται "μεθόδοι" στη Java. +// } + +class Bicycle { + +    // Πεδία/μεταβλητές της Κλάσης Bicycle +    // Public(Δημόσιες): Μπορούν να γίνουν προσβάσιμες από παντού +    public int cadence;  +    // Private(Ιδιωτικές): Προσβάσιμες μόνο εντός της κλάσης +    private int speed;   +    // Protected(Προστατευμένες): Προσβάσιμες από την κλάση και τις υποκλάσεις (subclasses) της +    protected int gear;  +    String name; // Προκαθορισμένο: Προσβάσιμη μόνο εντός του πακέτου + +    static String className; // Static μεταβλητή κλάσης + +    // Static block  +    // H Java δεν υποστηρίζει υλοποίησεις στατικών κατασκευαστών (static  +    // constructors), αλλά έχει ένα static block το οποίο μπορεί να  +    // χρησιμοποιηθεί για να αρχικοποιήσει στατικές μεταβλητές (static  +    // variables). Το block αυτό θα καλεσθεί όταν η κλάση φορτωθεί. +    static { +        className = "Bicycle"; +    } + +    // Οι κατασκευαστές (constructors) είναι ένας τρόπος για δημιουργία κλάσεων +    // Αυτός είναι ένας κατασκευαστής (constructor) +    public Bicycle() { +        // Μπορείς επίσης να καλέσεις άλλο κατασκευαστή: +        // this(1, 50, 5, "Bontrager"); +        gear = 1; +        cadence = 50; +        speed = 5; +        name = "Bontrager"; +    } + +    // Αυτός είναι ένας κατασκευαστής ο οποίος δέχεται arguments +    public Bicycle(int startCadence, int startSpeed, int startGear, +        String name) { +        this.gear = startGear; +        this.cadence = startCadence; +        this.speed = startSpeed; +        this.name = name; +    } + +    // Οι μεθόδοι (Methods) συντάσσονται ως ακολούθως: +    // <public/private/protected> <return type> <όνομα μεθόδου>(<args>) + +    // Οι κλάσεις Java συχνά υλοποιούν getters and setters for their fields + +    // Σύνταξη δήλωσης μεθόδου: +    // <Προσδιοριστές πρόσβασης> <τύπος επιστροφής> <όνομα μεθόδου>(<args>) +    public int getCadence() { +        return cadence; +    } + +    // Οι μεθόδοι void δεν απαιτούν return statement +    public void setCadence(int newValue) { +        cadence = newValue; +    } + +    public void setGear(int newValue) { +        gear = newValue; +    } + +    public void speedUp(int increment) { +        speed += increment; +    } + +    public void slowDown(int decrement) { +        speed -= decrement; +    } + +    public void setName(String newName) { +        name = newName; +    } + +    public String getName() { +        return name; +    } + +    //Μέθοδος η οποία επιστρέφει ως String τις τιμές των χαρακτηριστικών του  +    // αντικειμένου. +    @Override // Χρησιμοποιείται, καθώς η συγκεκριμένη μέθοδος κληρονομήθηκε από τη κλάση Object. +    public String toString() { +        return "gear: " + gear + " cadence: " + cadence + " speed: " + speed + +            " name: " + name; +    } +} // Τέλος κλάσης Bicycle + +// Η PennyFarthing είναι υποκλάση της Bicycle +class PennyFarthing extends Bicycle { +    // (Tα Penny Farthings είναι τα ποδήλατα με τον μεγάλο μπροστινό τροχό. +    // Δεν έχουν ταχύτητες.) + +    public PennyFarthing(int startCadence, int startSpeed) { +        // Κάλεσε τον parent constructor χρησιμοποιώντας το super +        super(startCadence, startSpeed, 0, "PennyFarthing"); +    } + +    // Χρειάζεται να μαρκάρεις τη μέθοδο την οποία κάνεις overriding  +    // χρησιμοποιώντας ένα @annotation. +    // Για να μάθεις περισσότερα σχετικά με το τι είναι οι επισημάνσεις  +    // (annotations) και τον σκοπό τους δες αυτό:  +    // http://docs.oracle.com/javase/tutorial/java/annotations/ +    @Override +    public void setGear(int gear) { +        gear = 0; +    } +} + +// Διεπαφές (Interfaces) +// Σύνταξη δήλωσης διεπαφής +// <access-level> interface <interface-name> extends <super-interfaces> { +//     // Σταθερές (Constants) +//     // Δηλώσεις Μεθόδων (Method declarations) +// } + +// Παράδειγμα - Food: +public interface Edible { +    public void eat(); // Κάθε κλάση η οποία υλοποιεί τη διεπαφή αυτή πρέπει  +    // να υλοποιήσει τη συγκεκριμένη μέθοδο. +} + +public interface Digestible { +    public void digest(); +} + + +// Μπορούμε να δημιουργήσουμε μία κλάση η οποία υλοποιεί και τις δύο αυτές διεπαφές. +public class Fruit implements Edible, Digestible { +   +    @Override +    public void eat() { +        // ... +    } + +    @Override +    public void digest() { +        // ... +    } +} + +// Στην Java, μπορείς να κληρονομήσεις (extend) από μόνο μία κλάση, +// αλλά μπορείς να υλοποιήσεις πολλές διεπαφές. Για παράδειγμα: +public class ExampleClass extends ExampleClassParent implements InterfaceOne, +    InterfaceTwo { + +    @Override +    public void InterfaceOneMethod() { +    } + +    @Override +    public void InterfaceTwoMethod() { +    } + +} + +// Abstract (Αφηρημένες) Κλάσεις + +// Σύνταξη Δήλωσης Abstract Κλάσης +// <access-level> abstract <abstract-class-name> extends <super-abstract-classes> { +//     // Σταθερές και μεταβλητές +//     // Δηλώσεις μεθόδων +// } + +// Μαρκάροντας μία κλάση ως abstract σημαίνει ότι περιέχει abstract μεθόδους +// οι οποίες πρέπει να οριστούν σε μία κλάση παιδί (child class). +// Παρόμοια με τις διεπαφές (interfaces), οι abstract κλάσεις δεν μπορούν να +// γίνουν instantiated, αλλά αντί αυτού πρέπει να γίνει extend και οι abstract +// μεθόδοι πρέπει να οριστούν. Διαφορετικά από τις Διεπαφές, οι abstract  +// κλάσεις μπορούν να περιέχουν τόσο υλοποιημένες όσο και abstract μεθόδους. +// Οι μεθόδοι σε μια Διεπαφή δεν μπορούν να έχουν σώμα (δεν είναι υλοποιημένες  +// δηλαδή εκτός εάν η μέθοδος είναι στατική και οι μεταβλητές είναι final by  +// default αντίθετα απο μία abstract κλάση. Επίσης, οι abstract κλάσεις  +// ΜΠΟΡΟΥΝ να έχουν την μέθοδο "main". + +public abstract class Animal +{ +    public abstract void makeSound(); + +    // Οι μεθόδοι μπορούν να έχουν σώμα (body) +    public void eat() +    { +        System.out.println("I am an animal and I am Eating.");   +        // Σημείωση: Μπορούμε να έχουμε πρόσβαση σε ιδιωτικές (private) μεταβλητές εδώ. +        age = 30; +    } + +    // Δεν χρειάζεται να αρχικοποιηθεί, εντούτοις σε ένα interface μία  +    // μεταβλητή είναι implicitly final και έτσι χρειάζεται να αρχικοποιηθεί +    protected int age; + +    public void printAge() +    { +        System.out.println(age);   +    } + +    // Οι Abstract κλάσεις μπορούν να έχουν συνάρτηση main. +    public static void main(String[] args) +    { +        System.out.println("I am abstract"); +    } +} + +class Dog extends Animal +{ +    // Σημείωση ότι χρειάζεται να κάνουμε override τις abstract μεθόδους στην +    // abstract κλάση. +    @Override +    public void makeSound() +    { +        System.out.println("Bark"); +        // age = 30;	==> ERROR!	Το πεδίο age είναι private στο Animal +    } + +    // ΣΗΜΕΙΩΣΗ: Θα πάρεις error εάν χρησιμοποίησεις το +    // @Override annotation εδώ, καθώς η java δεν επιτρέπει +    // να γίνονται override οι static μεθόδοι. +    // Αυτό που γίνεται εδώ ονομάζεται METHOD HIDING. +    // Για δες αυτό το εξαιρετικό ποστ στο SO (Stack Overflow): http://stackoverflow.com/questions/16313649/ +    public static void main(String[] args) +    { +        Dog pluto = new Dog(); +        pluto.makeSound(); +        pluto.eat(); +        pluto.printAge(); +    } +} + +// Κλάσεις Final + +// Σύνταξη δήλωσης μίας Final κλάσης +// <access-level> final <final-class-name> { +//     // Σταθερές και μεταβλητές +//     // Δήλωση μεθόδων +// } + +// Οι κλάσεις Final είναι κλάσεις οι οποίες δεν μπορούν να κληρονομηθούν και  +// συνεπώς είναι final child. In a way, final classes are the opposite of  +// abstract classes because abstract classes must be extended, but final  +// classes cannot be extended. +public final class SaberToothedCat extends Animal +{ +    // Σημείωση ότι χρειάζεται και πάλι να κάνουμε override τις abstract  +    // μεθόδους στην abstract κλάση. +    @Override +    public void makeSound() +    { +        System.out.println("Roar"); +    } +} + +// Τελικές (Final) μεθόδοι +public abstract class Mammal() +{ +    // Σύνταξη μίας Final μεθόδου: +    // <Προσδιοριστής πρόσβασης (access modifier)> final <τύπος επιστροφής> <Όνομα μεθόδου>(<args>) + +    // Οι Final μεθόδοι, όπως και οι final κλάσεις δεν μπορούν να γίνουν  +    // overridden από κλάση παιδί, +    // και είναι συνεπώς η τελική υλοποίηση της μεθόδου. +    public final boolean isWarmBlooded() +    { +        return true; +    } +} + + +// Τύποι Enum +// +// Ένας τύπος enum είναι ένας ειδικός τύπος δεδομένων, ο οποίος επιτρέπει σε  +// μια μεταβλητή να είναι ένα σύνολο από προκαθορισμένες σταθερές. Η μεταβλητή  +// πρέπει να είναι ίση με μία από τις τιμές αυτές που έχουν προκαθοριστεί.  +// Επειδή είναι σταθερές, τα ονόματα ενός enum πεδίου γράφονται με κεφαλαίους  +// χαρακτήρες. Στην γλώσσα προγραμματισμού Java, ορίζεις ένα τύπο enum  +// χρησιμοποιώντας τη δεσμευμένη λέξη enum. Για παράδειγμα, θα μπορούσες να  +// καθορίσεις ένα τύπο enum με όνομα days-of-the-week ως: + +public enum Day { +    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, +    THURSDAY, FRIDAY, SATURDAY  +} + +// Μπορούμε να χρησιμοποιήσουμε τον enum Day όπως παρακάτω: + +public class EnumTest { +     +    // Μεταβλητή Enum +    Day day; +     +    public EnumTest(Day day) { +        this.day = day; +    } +     +    public void tellItLikeItIs() { +        switch (day) { +            case MONDAY: +                System.out.println("Mondays are bad."); +                break; +                     +            case FRIDAY: +                System.out.println("Fridays are better."); +                break; +                          +            case SATURDAY:  +            case SUNDAY: +                System.out.println("Weekends are best."); +                break; +                         +            default: +                System.out.println("Midweek days are so-so."); +                break; +        } +    } +     +    public static void main(String[] args) { +        EnumTest firstDay = new EnumTest(Day.MONDAY); +        firstDay.tellItLikeItIs(); // => Mondays are bad. +        EnumTest thirdDay = new EnumTest(Day.WEDNESDAY); +        thirdDay.tellItLikeItIs(); // => Midweek days are so-so. +    } +} + +// Οι τύποι Enum είναι πολύ πιο δυνατοί από όσο έχουμε δείξει πιο πάνω.  +// Το σώμα του enum (enum body) μπορεί να περιέχει μεθόδους και άλλα πεδία. +// Μπορείς να δεις περισσότερα στο  +// https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html + +``` + +## Επιπλέων διάβασμα + +Οι σύνδεσμοι που παρέχονται εδώ είναι απλά για να κατανοήσεις περισσότερο το θέμα. +Σε προτρύνουμε να ψάξεις στο Google και να βρεις συγκεκριμένα παραδείγματα. + +**Eπίσημοι Οδηγοί της Oracle**: + +* [Φροντιστήριο εκμάθησης Java από τη Sun / Oracle](http://docs.oracle.com/javase/tutorial/index.html) + +* [Τροποποιητές επιπέδου πρόσβασης(Access level modifiers) Java](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) + +* [Έννοιες αντικειμενοστραφούς (Object-Oriented) προγραμματισμού](http://docs.oracle.com/javase/tutorial/java/concepts/index.html): +    * [Κληρονομικότητα (Inheritance)](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html) +    * [Πολυμορφισμός (Polymorphism)](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) +    * [Αφαιρετικότητα (Abstraction)](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) + +* [Εξαιρέσεις (Exceptions)](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html) + +* [Διεπαφές (Interfaces)](http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html) + +* [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html) + +* [Συμβάσεις κώδικα Java (Code Conventions)](http://www.oracle.com/technetwork/java/codeconvtoc-136057.html) + +**Πρακτικές και Φροντιστήρια Online** + +* [Learneroo.com - Μάθε Java](http://www.learneroo.com) + +* [Codingbat.com](http://codingbat.com/java) + + +**Βιβλία**: + +* [Head First Java](http://www.headfirstlabs.com/books/hfjava/) + +* [Thinking in Java](http://www.mindview.net/Books/TIJ/) + +* [Objects First with Java](http://www.amazon.com/Objects-First-Java-Practical-Introduction/dp/0132492660) + +* [Java The Complete Reference](http://www.amazon.com/gp/product/0071606300) diff --git a/el-gr/racket-gr.html.markdown b/el-gr/racket-gr.html.markdown new file mode 100644 index 00000000..589adfeb --- /dev/null +++ b/el-gr/racket-gr.html.markdown @@ -0,0 +1,745 @@ +--- +language: racket +filename: learnracket-gr.rkt +contributors: +  - ["th3rac25", "https://github.com/voila"] +  - ["Eli Barzilay", "https://github.com/elibarzilay"] +  - ["Gustavo Schmidt", "https://github.com/gustavoschmidt"] +  - ["Duong H. Nguyen", "https://github.com/cmpitg"] +  - ["Keyan Zhang", "https://github.com/keyanzhang"] +translators: +  - ["Vasilis Panagiotopoulos" , "https://github.com/billpcs/"] +lang: el-gr +--- + +H Racket είναι μια γενικού σκοπού, πολυ-υποδειγματική γλώσσα προγραμματισμού που ανήκει  +στην οικογένεια της Lisp/Scheme + +```racket +#lang racket ; ορίζει την γλώσσα που χρησιμοποιόυμε + +;;; Σχόλια + +;; Τα σχόλια μιας γραμμής ξεκινούν με ερωτηματικό + +#| Τα σχόλια ολόκληρου μπλόκ +   μπορούν να εκτείνονται σε πολλές γραμμές και... +    #| +       μπορούν να είναι εμφωλευμένα! +    |# +|# + +;; Τα σχόλια S-expression (εκφράσεις S) comments απορρίπτουν την +;; έκφραση που ακολουθεί, δυνατότητα που είναι χρήσιμη για να +;; κάνουμε σχόλια κάποιες εκφράσεις κατά τη διάρκεια του debugging + +#; (αυτή η έκφραση δεν θα εκτελεστεί) + +;; (Αν δεν καταλαβαίνεται τι είναι οι εκφράσεις , περιμένετε... Θα το μάθουμε +;; πολύ σύντομα!) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 1. Πρωτογενείς τύποι μεταβλητών και τελεστές +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Αριθμοί +9999999999999999999999 ; ακέραιοι +#b111                  ; δυαδικοί => 7 +#o111                  ; οκταδικοί => 73 +#x111                  ; δεκαεξαδικοί => 273 +3.14                   ; πραγματικοί +6.02e+23 +1/2                    ; ρητοί +1+2i                   ; μιγαδικοί + +;; Οι μορφή των συναρτήσεων είναι (f x y z) +;; όπου το f είναι η συνάρτηση και τα x y z +;; είναι οι όροι που η συνάρτηση δέχεται +;; ως ορίσματα. Αν θέλουμε να δημιουργήσουμε +;; μια λίστα στην κυριολεξία από δίαφορα δεδομένα, +;; χρησιμοποιούμε το ' για να το εμποδίσουμε από το να +;; αξιολογηθεί σαν έκφραση. Για παράδειγμα: +'(+ 1 2) ; => Παραμένει (+ 1 2) και δεν γίνεται η πράξη +;; Τώρα , ας κάνουμε μερικές πράξεις +(+ 1 1)  ; => 2 +(- 8 1)  ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(quotient 5 2) ; => 2 +(remainder 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(exact->inexact 1/3) ; => 0.3333333333333333 +(+ 1+2i  2-3i) ; => 3-1i + +;;; Λογικές μεταβλητές +#t ; για το true (αληθής) +#f ; για το false (ψευδής) +(not #t) ; => #f +(and 0 #f (error "doesn't get here")) ; => #f +(or #f 0 (error "doesn't get here"))  ; => 0 + +;;; Χαρακτήρες +#\A ; => #\A +#\λ ; => #\λ +#\u03BB ; => #\λ + +;;; Τα αλφαριθμητικά είναι πίνακες χαρακτήρων συγκεκριμένου μήκους +"Hello, world!" +"Benjamin \"Bugsy\" Siegel"   ; Το backslash είναι χαρακτήρας διαφυγής +"Foo\tbar\41\x21\u0021\a\r\n" ; Συμπεριλαμβάνονται οι χαρακτήρες διαφυγής της C, +							  ; σε Unicode +"λx:(μα.α→α).xx"              ; Μπορούν να υπάρχουν και Unicode χαρακτήρες + +;; Μπορούμε να ενώσουμε αλφαριθμητικά! +(string-append "Hello " "world!") ; => "Hello world!" + +;; Ένα αλφαριθμητικό μπορούμε να το χρησιμοποιήσουμε +;; όπως και μια λίστα από χαρακτήρες +(string-ref "Apple" 0) ; => #\A ;; Παίρνουμε το πρώτο στοιχείο + +;; Η συνάρτηση format μπορεί να χρησιμοποιηθεί για +;; να μορφοποιήσουμε αλφαριθμητικά +(format "~a can be ~a" "strings" "formatted") ;; => "strings can be formatted" + +;; Η εκτύπωση είναι εύκολη. +(printf "I'm Racket. Nice to meet you!\n") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. Μεταβλητές +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Μπορούμε να δημιουργήσουμε μεταβλητές +;; χρησιμοποιώντας το define. +;; Ένα όνομα μεταβλητής μπορεί να χρησιμοποιεί οποιονδήποτε  +;; χαρακτήρα, εκτός από τους: ()[]{}",'`;#|\ +(define some-var 5) +some-var ; => 5 + +;; Μπορούμε επίσης να χρησιμοποιήσουμε unicode χαρακτήρες. +(define ⊆ subset?) ;; Εδώ ουσιαστικά δίνουμε στη ήδη υπάρχουσα συνάρτηση subset? +				   ;; ένα νέο όνομα ⊆ , και παρακάτω την καλούμε με το νέο της όνομα. +(⊆ (set 3 2) (set 1 2 3)) ; => #t + +;; Αν ζητήσουμε μια μεταβλητή που δεν έχει οριστεί πριν π.χ. +(printf name) +;; θα πάρουμε το παρακάτω μήνυμα +;name: undefined; +;  cannot reference undefined identifier +;   context...: + +;; Η τοπική δέσμευση : `me' δεσμεύεται με το "Bob" μόνο μέσα στο (let ...) +(let ([me "Bob"]) +  "Alice" +  me) ; => "Bob" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Δομές και συλλογές +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Δομές +(struct dog (name breed age)) +(define my-pet +  (dog "lassie" "collie" 5)) +my-pet ; => #<dog> +(dog? my-pet) ; => #t +(dog-name my-pet) ; => "lassie" + +;;; Ζεύγη (αμετάβλητα) +;; Η δεσμευμένη λέξη `cons' δημιουργεί ζεύγη, +;; και το `car' και το `cdr' εξάγουν το πρώτο και +;; το δεύτερο στοιχείο αντίστοιχα. +(cons 1 2) ; => '(1 . 2) +(car (cons 1 2)) ; => 1 +(cdr (cons 1 2)) ; => 2 + +;;; Λίστες + +;; Οι λίστες είναι linked-list δομές δεδομένων, +;; που έχουν δημιουργηθεί από ζευγάρια 'cons' +;; και τελειώνουν με 'null' (ή αλλιώς '()) για να +;; δηλώσουν ότι αυτό είναι το τέλος της λίστας +(cons 1 (cons 2 (cons 3 null))) ; => '(1 2 3) +;; Η δεσμευμένη λέξη  'list' είναι ένας εναλλακτικός +;; (και σαφώς πιο βολικός) τρόπος για να δημιουργούμε +;; λίστες +(list 1 2 3) ; => '(1 2 3) +;; αλλά και χρησιμοποιώντας ένα μονό εισαγωγικό το +;; το αποτέλεσμα είναι και πάλι το ίδιο +'(1 2 3) ; => '(1 2 3) + +;; Μπορούμε και πάλι όμως να χρησιμοποιούμε το 'cons' για να +;; προσθέσουμε ένα στοιχείο στην αρχή της λίστας +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;; Μπορούμε να χρησιμοποιούμε το 'append' για να προσθέτουμε +;; στοιχεία στο τέλος μιας λίστας. Το στοιχείο αυτό μπορεί +;; και να είναι ολόκληρη λίστα! +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;; Οι λίστες στην Racket είναι πολύ βασικές , οπότε υπάρχουν πολλές +;; δυνατές λειτουργίες για αυτές. Παρακάτω είναι μερικά παραδείγματα: +(map add1 '(1 2 3))          ; => '(2 3 4) +(map + '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(filter even? '(1 2 3 4))    ; => '(2 4) +(count even? '(1 2 3 4))     ; => 2 +(take '(1 2 3 4) 2)          ; => '(1 2) +(drop '(1 2 3 4) 2)          ; => '(3 4) + +;;; Διανύσματα + +;; Τα διανύσματα είναι πίνακες σταθερού μήκους +#(1 2 3) ; => '#(1 2 3) + +;; Χρησιμοποιούμε το `vector-append' για να προσθέσουμε διανύσματα +(vector-append #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + +;;; Σύνολα + +;; Δημιουργούμε ένα σύνολο από μία λίστα +(list->set '(1 2 3 1 2 3 3 2 1 3 2 1)) ; => (set 1 2 3) + +;; Προσθέτουμε έναν αριθμό στο σύνολο χρησιμοποιώντας το `set-add' +(set-add (set 1 2 3) 4) ; => (set 1 2 3 4) + +;; Αφαιρούμε με το `set-remove' +(set-remove (set 1 2 3) 1) ; => (set 2 3) + +;; Βλέπουμε αν υπάρχει ένας αριθμός στο σύνολο με το `set-member?' +(set-member? (set 1 2 3) 1) ; => #t +(set-member? (set 1 2 3) 4) ; => #f + +;;; Πίνακες κατακερματισμού (Hashes) + +;; Δημιουργήστε ένα αμετάβλητο πίνακα κατακερματισμού +(define m (hash 'a 1 'b 2 'c 3)) + +;; Παίρνουμε μια τιμή από τον πίνακα +(hash-ref m 'a) ; => 1 + +;; Αν ζητήσουμε μια τιμή που δεν υπάρχει παίρνουμε μία εξαίρεση +; (hash-ref m 'd) => no value found for key + +;; Μπορούμε να δώσουμε μια default τιμή για τα κλειδιά που λείπουν +(hash-ref m 'd 0) ; => 0 + + +;; Χρησιμοποιούμε το 'hash-set' για να επεκτείνουμε +;; ένα πίνακα κατακερματισμού +(define m2 (hash-set m 'd 4)) +m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3)) + +;; Θυμηθείτε ! Αυτοί οι πίνακες κατακερματισμού +;; είναι αμετάβλητοι! +m ; => '#hash((b . 2) (a . 1) (c . 3))  <-- δεν υπάρχει `d' + +;; Χρησιμοποιούμε το `hash-remove' για να αφαιρέσουμε +;; κλειδιά +(hash-remove m 'a) ; => '#hash((b . 2) (c . 3)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. Συναρτήσεις +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Χρησιμοποιούμε το `lambda' για να δημιουργήσουμε συναρτήσεις. +;; Μια συνάρτηση πάντα επιστρέφει την τιμή της τελευταίας της έκφρασης +(lambda () "Hello World") ; => #<procedure> +;; Μπορούμε επίσης να χρησιμοποιήσουμε το `λ' +(λ () "Hello World")     ; => Ίδια συνάρτηση + +;; Χρησιμοποιούμε τις παρενθέσεις για να καλέσουμε όλες τις συναρτήσεις +;; συμπεριλαμβανομένων και των εκφράσεων 'λάμδα' +((lambda () "Hello World")) ; => "Hello World" +((λ () "Hello World"))      ; => "Hello World" + +;; Εκχωρούμε σε μια μεταβλητή την συνάρτηση +(define hello-world (lambda () "Hello World")) +(hello-world) ; => "Hello World" + +;; Μπορούμε αυτό να το κάνουμε συντομότερο χρησιμοποιώντας +;; το λεγόμενο syntactic sugar : +(define (hello-world2) "Hello World") + +;; Το () στο παραπάνω είναι η λίστα από τα ορίσματα για την συνάρτηση + +(define hello +  (lambda (name) +    (string-append "Hello " name))) +(hello "Steve") ; => "Hello Steve" +;; ... ή ισοδύναμα, χρησιμοποιώντας sugared ορισμό: +(define (hello2 name) +  (string-append "Hello " name)) + +;; Μπορούμε να έχουμε συναρτήσεις με πολλές μεταβλητές χρησιμοποιώντας +;; το `case-lambda' +(define hello3 +  (case-lambda +    [() "Hello World"] +    [(name) (string-append "Hello " name)])) +(hello3 "Jake") ; => "Hello Jake" +(hello3) ; => "Hello World" +;; ... ή να ορίσουμε προαιρετικά ορίσματα με μια έκφραση προκαθορισμένης τιμής +(define (hello4 [name "World"]) +  (string-append "Hello " name)) + +;; Οι συναρτήσεις μπορούν να πακετάρουν επιπλέον +;; ορίσματα μέσα σε μια λίστα +(define (count-args . args) +  (format "You passed ~a args: ~a" (length args) args)) +(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" +;; ... ή με unsugared μορφή `lambda': +(define count-args2 +  (lambda args +    (format "You passed ~a args: ~a" (length args) args))) + +;; Μπορούμε να εμπλέξουμε κανονικά και πακεταρισμένα ορίσματα +(define (hello-count name . args) +  (format "Hello ~a, you passed ~a extra args" name (length args))) +(hello-count "Finn" 1 2 3) +; => "Hello Finn, you passed 3 extra args" +;; ... και unsugared: +(define hello-count2 +  (lambda (name . args) +    (format "Hello ~a, you passed ~a extra args" name (length args)))) + +;; Και με λέξεις κλειδιά +(define (hello-k #:name [name "World"] #:greeting [g "Hello"] . args) +  (format "~a ~a, ~a extra args" g name (length args))) +(hello-k)                 ; => "Hello World, 0 extra args" +(hello-k 1 2 3)           ; => "Hello World, 3 extra args" +(hello-k #:greeting "Hi") ; => "Hi World, 0 extra args" +(hello-k #:name "Finn" #:greeting "Hey") ; => "Hey Finn, 0 extra args" +(hello-k 1 2 3 #:greeting "Hi" #:name "Finn" 4 5 6) +                                         ; => "Hi Finn, 6 extra args" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. Ισότητα +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; για αριθμούς χρησιμοποιούμε το `=' +(= 3 3.0) ; => #t +(= 2 1)   ; => #f + +;; Το `eq?' επιστρέφει #t αν δύο 2 ορίσματα αναφέρονται στο +;; ίδιο αντικείμενο (στη μνήμη),αλλιώς επιστρέφει #f. +;; Με άλλα λόγια, είναι απλή σύγκριση δεικτών. +(eq? '() '()) ; => #t, αφού υπάρχει μόνο μια άδεια λίστα στη μνήμη +(let ([x '()] [y '()]) +  (eq? x y))  ; => #t, το ίδιο με πάνω + +(eq? (list 3) (list 3)) ; => #f +(let ([x (list 3)] [y (list 3)]) +  (eq? x y))            ; => #f — δεν είναι η ίδια λίστα στην μνήμη! + +(let* ([x (list 3)] [y x]) +  (eq? x y)) ; => #t, Αφού το x και το y τώρα δείχνουν στην ίδια θέση + +(eq? 'yes 'yes) ; => #t +(eq? 'yes 'no)  ; => #f + +(eq? 3 3)   ; => #t — να είστε προσεκτικοί εδώ +            ; Είναι προτιμότερο να χρησιμοποιείτε `=' για την +            ; σύγκριση αριθμών. +(eq? 3 3.0) ; => #f + +(eq? (expt 2 100) (expt 2 100))               ; => #f +(eq? (integer->char 955) (integer->char 955)) ; => #f + +(eq? (string-append "foo" "bar") (string-append "foo" "bar")) ; => #f + +;; Το `eqv?' υποστηρίζει την σύγκριση αριθμών αλλά και χαρακτήρων +;; Για άλλα ήδη μεταβλητών το `eqv?' και το `eq?' επιστρέφουν το ίδιο. +(eqv? 3 3.0)                                   ; => #f +(eqv? (expt 2 100) (expt 2 100))               ; => #t +(eqv? (integer->char 955) (integer->char 955)) ; => #t + +(eqv? (string-append "foo" "bar") (string-append "foo" "bar"))   ; => #f + +;; Το `equal?' υποστηρίζει την σύγκριση των παρακάτω τύπων μεταβλητών: +;; αλφαριθμητικά, αλφαριθμητικά από bytes, μεταβλητά ζεύγη , διανύσματα, +;; πίνακες κατακερματισμού και δομές. +;; Για άλλα ήδη τύπων μεταβλητών το `equal?' και το `eqv?' επιστρέφουν το +;; ίδιο αποτέλεσμα. +(equal? 3 3.0)                                                   ; => #f +(equal? (string-append "foo" "bar") (string-append "foo" "bar")) ; => #t +(equal? (list 3) (list 3))                                       ; => #t + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. Έλεγχος Ροής +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Συνθήκες (conditionals) + +(if #t               ; έκφραση ελέγχου +    "this is true"   ; έκφραση then +    "this is false") ; έκφραση else +; => "this is true" + + +;; Στα conditionals, όλες οι μη #f τιμές θεωρούνται ως #t +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(Groucho Zeppo) +(if (member 'Groucho '(Harpo Groucho Zeppo)) +    'yep +    'nope) +; => 'yep + +;; Οι αλυσίδες `cond' είναι σειρές από ελέγχους για να +;; επιλεγεί ένα αποτέλεσμα +(cond [(> 2 2) (error "wrong!")] +      [(< 2 2) (error "wrong again!")] +      [else 'ok]) ; => 'ok + +;;; Αντιστοίχιση μοτίβων + +(define (fizzbuzz? n) +  (match (list (remainder n 3) (remainder n 5)) +    [(list 0 0) 'fizzbuzz] +    [(list 0 _) 'fizz] +    [(list _ 0) 'buzz] +    [_          #f])) + +(fizzbuzz? 15) ; => 'fizzbuzz +(fizzbuzz? 37) ; => #f + +;;; Βρόχοι + +;; Οι επαναλήψεις μπορούν να γίνουν μέσω αναδρομής +(define (loop i) +  (when (< i 10) +    (printf "i=~a\n" i) +    (loop (add1 i)))) +(loop 5) ; => i=5, i=6, ... + +;; Παρομοίως με τη χρήση 'let' +(let loop ((i 0)) +  (when (< i 10) +    (printf "i=~a\n" i) +    (loop (add1 i)))) ; => i=0, i=1, ... + + +;; Θα δείτε παρακάτω πως να προσθέσουμε μια νέα μορφή επανάληψης +;; αλλά η Racket έχει ήδη πολύ ευέλικτη μορφή για τους βρόχους +(for ([i 10]) +  (printf "i=~a\n" i)) ; => i=0, i=1, ... +(for ([i (in-range 5 10)]) +  (printf "i=~a\n" i)) ; => i=5, i=6, ... + +;;; +;;; Επανάληψη μέσα σε ακολουθίες: +;; Το `for' επιτρέπει την επανάληψη μέσα σε πολλά +;; άλλα ήδη από ακολουθίες: Λίστες, διανύσματα, +;; αλφαριθμητικά, σύνολα κτλ.. + +(for ([i (in-list '(l i s t))]) +  (displayln i)) + +(for ([i (in-vector #(v e c t o r))]) +  (displayln i)) + +(for ([i (in-string "string")]) +  (displayln i)) + +(for ([i (in-set (set 'x 'y 'z))]) +  (displayln i)) + +(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3 ))]) +  (printf "key:~a value:~a\n" k v)) + +;;; Πιο περίπλοκες επαναλήψεις + +;; Παράλληλη σάρωση σε πολλαπλές ακολουθίες +;; (σταματά στην πιο σύντομη) +(for ([i 10] [j '(x y z)]) (printf "~a:~a\n" i j)) +; => 0:x 1:y 2:z + +;; Εμφολευμένοι βρόχοι +(for* ([i 2] [j '(x y z)]) (printf "~a:~a\n" i j)) +; => 0:x, 0:y, 0:z, 1:x, 1:y, 1:z + +;; Συνθήκες +(for ([i 1000] +      #:when (> i 5) +      #:unless (odd? i) +      #:break (> i 10)) +  (printf "i=~a\n" i)) +; => i=6, i=8, i=10 + +;;; Σάρωση σε λίστες +;; Παρόμοιο με τους βρόχους 'for', απλά συλλέγουμε τα αποτελέσματα + +(for/list ([i '(1 2 3)]) +  (add1 i)) ; => '(2 3 4) + +(for/list ([i '(1 2 3)] #:when (even? i)) +  i) ; => '(2) + +(for/list ([i 10] [j '(x y z)]) +  (list i j)) ; => '((0 x) (1 y) (2 z)) + +(for/list ([i 1000] #:when (> i 5) #:unless (odd? i) #:break (> i 10)) +  i) ; => '(6 8 10) + +(for/hash ([i '(1 2 3)]) +  (values i (number->string i))) +; => '#hash((1 . "1") (2 . "2") (3 . "3")) + +;; Υπάρχουν πολλά είδη από προϋπάρχοντες τρόπους για να συλλέγουμε +;; τιμές από τους βρόχους + +(for/sum ([i 10]) (* i i)) ; => 285 +(for/product ([i (in-range 1 11)]) (* i i)) ; => 13168189440000 +(for/and ([i 10] [j (in-range 10 20)]) (< i j)) ; => #t +(for/or ([i 10] [j (in-range 0 20 2)]) (= i j)) ; => #t + +;; Και για να χρησιμοποιήσουμε ένα αυθαίρετο συνδυασμό χρησιμοποιούμε +;; το 'for/fold' +(for/fold ([sum 0]) ([i '(1 2 3 4)]) (+ sum i)) ; => 10 + +;; Αυτό συχνά μπορεί να αντικαταστήσει τους κοινούς +;; προστακτικούς βρόχους (imperative loops) + +;;; Εξαιρέσεις + +;; Για να πιάσουμε τις εξαιρέσεις χρησιμοποιούμε το +;; `with-handlers' +(with-handlers ([exn:fail? (lambda (exn) 999)]) +  (+ 1 "2")) ; => 999 +(with-handlers ([exn:break? (lambda (exn) "no time")]) +  (sleep 3) +  "phew") ; => "phew", αλλά αν γίνει το break => "no time" + +;; Χρησιμοποιούμε το 'raise' για να άρουμε μια εξαίρεση +;; ή οποιαδήποτε άλλη τιμή +(with-handlers ([number?    ; πιάνουμε αριθμητικές τιμές +                 identity]) ; και τις επιστρέφουμε σαν απλές τιμές +  (+ 1 (raise 2))) ; => 2 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. Αλλαγή τιμών +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Χρησιμοποιούμε το 'set!' για να θέσουμε μια νέα τιμή +;; σε μια ήδη υπάρχουσα μεταβλητή +(define n 5) +(set! n (add1 n)) +n ; => 6 + +;; Χρησιμοποιούμε τα boxes για να δηλώσουμε ρητά ότι μια μεταβλητή +;; θα είναι  mutable (θα μπορεί να αλλάξει η τιμή της) +;; Αυτό είναι παρόμοιο με τους pointers σε άλλες γλώσσες +(define n* (box 5)) +(set-box! n* (add1 (unbox n*))) +(unbox n*) ; => 6 + + +;; Πολλοί τύποι μεταβλητών στη Racket είναι αμετάβλητοι π.χ. τα ζεύγη, οι +;; λίστες κτλ. Άλλοι υπάρχουν και σε μεταβλητή και σε αμετάβλητη μορφή +;; π.χ. αλφαριθμητικά, διανύσματα κτλ. +(define vec (vector 2 2 3 4)) +(define wall (make-vector 100 'bottle-of-beer)) +;; Χρησιμοποιούμε το 'vector-set!' για να ανεώσουμε κάποια +;; συγκεκριμένη θέση +(vector-set! vec 0 1) +(vector-set! wall 99 'down) +vec ; => #(1 2 3 4) + + +;; Έτσι δημιουργούμε ένα άδειο μεταβλητό πίνακα κατακερματισμού +;; και τον χειριζόμαστε κατάλληλα +(define m3 (make-hash)) +(hash-set! m3 'a 1) +(hash-set! m3 'b 2) +(hash-set! m3 'c 3) +(hash-ref m3 'a)     ; => 1 +(hash-ref m3 'd 0)   ; => 0 +(hash-remove! m3 'a) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. Ενότητες (modules) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;; Οι ενότητες μας επιτρέπουν να οργανώνουμε τον κώδικα σε πολλαπλά +;; αρχεία και επαναχρησιμοποιούμενες βιβλιοθήκες +;; Εδώ χρησιμοποιούμε υπο-ενότητες, εμφωλευμένες μέσα σε μια +;; άλλη ενότητα που δημιουργεί αυτό το κείμενο (ξεκινώντας από +;; την γραμμή '#lang' ) +(module cake racket/base ; ορίζουμε μια ενότητα 'cake' βασισμένο στο +                         ; racket/base + +  (provide print-cake) ; συνάρτηση που εξάγεται από την ενότητα + +  (define (print-cake n) +    (show "   ~a   " n #\.) +    (show " .-~a-. " n #\|) +    (show " | ~a | " n #\space) +    (show "---~a---" n #\-)) + +  (define (show fmt n ch) ; εσωτερική συνάρτηση +    (printf fmt (make-string n ch)) +    (newline))) + +;; Χρησιμοποιουμε το 'require' για να πάρουμε όλα τα +;; παρεχόμενα ονόματα από μία ενότητα +(require 'cake) ; το ' είναι για τοπική υποενότητα +(print-cake 3) +; (show "~a" 1 #\A) ; => error, το `show' δεν έχει εξαχθεί + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 8. Κλάσεις και αντικείμενα +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Δημιουργούμε μια κλάση fish% (- συνήθως χρησιμοποιούμε +;; το % στο όνομα μιας κλάσης ) +(define fish% +  (class object% +    (init size) ; initialization argument +    (super-new) ; superclass initialization +    ;; Field +    (define current-size size) +    ;; Public methods +    (define/public (get-size) +      current-size) +    (define/public (grow amt) +      (set! current-size (+ amt current-size))) +    (define/public (eat other-fish) +      (grow (send other-fish get-size))))) + +;; Δημιουργούμε ένα instance του fish% +(define charlie +  (new fish% [size 10])) + +;; Χρησιμοποιούμε το 'send' για να καλέσουμε +;; τις μεθόδους ενός αντικειμένου +(send charlie get-size) ; => 10 +(send charlie grow 6) +(send charlie get-size) ; => 16 + +;; Το `fish%' είναι μία τιμή "πρώτης κλάσης" +;; με το οποίο μπορούμε να κάνουμε προσμείξεις +(define (add-color c%) +  (class c% +    (init color) +    (super-new) +    (define my-color color) +    (define/public (get-color) my-color))) +(define colored-fish% (add-color fish%)) +(define charlie2 (new colored-fish% [size 10] [color 'red])) +(send charlie2 get-color) +;; ή χωρίς καθόλου ονόματα : +(send (new (add-color fish%) [size 10] [color 'red]) get-color) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 9. Μακροεντολές +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Οι μακροεντολές μας επιτρέπουν να επεκτείνουμε +;; το συντακτικό μιας γλώσσας. + +;; Ας προσθέσουμε έναν βρόχο while +(define-syntax-rule (while condition body ...) +  (let loop () +    (when condition +      body ... +      (loop)))) + +(let ([i 0]) +  (while (< i  10) +    (displayln i) +    (set! i (add1 i)))) + +;; Macros are hygienic, you cannot clobber existing variables! +(define-syntax-rule (swap! x y) ; -! is idiomatic for mutation +  (let ([tmp x]) +    (set! x y) +    (set! y tmp))) + +(define tmp 2) +(define other 3) +(swap! tmp other) +(printf "tmp = ~a; other = ~a\n" tmp other) +;; Η μεταβλητή 'tmp' μετονομάζεται σε 'tmp_1' +;; για να αποφευχθεί η σύγκρουση με τα ονόματα +;; (let ([tmp_1 tmp]) +;;   (set! tmp other) +;;   (set! other tmp_1)) + +;; Αλλά ακόμα υπάρχουν ακόμη μετασχηματισμοί του κώδικα, π.χ.: +(define-syntax-rule (bad-while condition body ...) +  (when condition +    body ... +    (bad-while condition body ...))) +;; αυτή η μακροεντολή είναι χαλασμένη: δημιουργεί ατέρμονα βρόχο +;; και αν προσπαθήσουμε να το χρησιμοποιήσουμε, ο μεταγλωττιστής +;; θα μπει στον ατέρμονα βρόχο. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 10. Συμβόλαια (Contracts) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Τα συμβόλαια βάζουν περιορισμούς σε τιμές που προέρχονται +;; από ενότητες (modules) +(module bank-account racket +  (provide (contract-out +            [deposit (-> positive? any)] ; οι ποσότητες είναι πάντα θετικές +            [balance (-> positive?)])) + +  (define amount 0) +  (define (deposit a) (set! amount (+ amount a))) +  (define (balance) amount) +  ) + +(require 'bank-account) +(deposit 5) + +(balance) ; => 5 + +;; Πελάτες που προσπαθούν να καταθέσουν ένα μη θετικό ποσό παίρνουν +;; το μήνυμα (deposit -5) ; => deposit: contract violation +;;                              expected: positive? +;;                              given: -5 +;;                              more details.... + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 11. Είσοδος και έξοδος +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Η Racket έχει την έννοια του "port", που είναι παρόμοιο με τα +;; file descriptors σε άλλες γλώσσες. + +;; Ανοίγουμε το "/tmp/tmp.txt" και γράφουμε μέσα "Hello World" +;; Αυτό θα προκαλούσε σφάλμα αν το αρχείο υπήρχε ήδη +(define out-port (open-output-file "/tmp/tmp.txt")) +(displayln "Hello World" out-port) +(close-output-port out-port) + +;; Προσθέτουμε στο τέλος του "/tmp/tmp.txt" +(define out-port (open-output-file "/tmp/tmp.txt" +                                   #:exists 'append)) +(displayln "Hola mundo" out-port) +(close-output-port out-port) + +;; Διαβάζουμε από αρχείο ξανά +(define in-port (open-input-file "/tmp/tmp.txt")) +(displayln (read-line in-port)) +; => "Hello World" +(displayln (read-line in-port)) +; => "Hola mundo" +(close-input-port in-port) + +;; Εναλλακτικά, με το call-with-output-file δεν χρειάζεται να κλείσουμε +;; ρητά το αρχείο +(call-with-output-file "/tmp/tmp.txt" +  #:exists 'update ; Rewrite the content +  (λ (out-port) +    (displayln "World Hello!" out-port))) + +;; Και το call-with-input-file κάνει το ίδιο πράγμα για την είσοδο +(call-with-input-file "/tmp/tmp.txt" +  (λ (in-port) +    (displayln (read-line in-port)))) +``` + +## Επιπλέον πηγές + +Ψάχνεις για περισσότερα ; [Getting Started with Racket](http://docs.racket-lang.org/getting-started/) diff --git a/el-gr/scala-gr.html.markdown b/el-gr/scala-gr.html.markdown new file mode 100644 index 00000000..415fda5c --- /dev/null +++ b/el-gr/scala-gr.html.markdown @@ -0,0 +1,689 @@ +--- +language: Scala +contributors: +    - ["George Petrov", "http://github.com/petrovg"] +    - ["Dominic Bou-Samra", "http://dbousamra.github.com"] +    - ["Geoff Liu", "http://geoffliu.me"] +translators: +    - ["Vasilis Panagiotopoulos" , "https://github.com/billpcs/"] +filename: learnscala-gr.scala +lang: el-gr +--- + +Scala - Η επεκτάσιμη γλώσσα + +```scala + +/* +  Προετοιμαστείτε: + +  1) Κατεβάστε την Scala - http://www.scala-lang.org/downloads +  2) Κάνετε εξαγωγή στην επιθυμητή σας τοποθεσία και βάλτε τον υποφάκελο bin +      στο path του συστήματος +  3) Ξεκινήστε ένα scala REPL γράφοντας scala. Θα πρέπει να βλέπετε το prompt: + +  scala> + +  Αυτό είναι το αποκαλούμενο REPL (Read-Eval-Print Loop) *. +  Μπορείτε να πληκτρολογήσετε οποιαδήποτε έγκυρη έκφραση σε Scala μέσα του , +  και το αποτέλεσμα θα τυπωθεί. Θα εξηγήσουμε πως μοιάζουν τα αρχεία της Scala +  αργότερα μέσα στο tutorial , αλλά για τώρα ας αρχίσουμε με κάποια βασικά. +  *[Βρόχος του Διάβασε - Αξιολόγησε - Τύπωσε] +*/ + + +///////////////////////////////////////////////// +// 1. Βασικές έννοιες +///////////////////////////////////////////////// + +// Τα σχόλια μίας γραμμής ξεκινούν με δύο "/" (:forward slashes) . + +/* +  Τα σχόλια που επεκτείνονται σε πολλές γραμμές , όπως μπορείτε +  να δείτε , φαίνονται κάπως έτσι. +*/ + +// Εκτύπωση με νέα γραμμή στην επόμενη εκτύπωση +println("Hello world!") +println(10) + +// Εκτύπωση χωρίς νέα γραμμή στην επόμενη εκτύπωση +print("Hello world") + +// Η δήλωση μεταβλητών γίνεται χρησιμοποιώντας var ή val. +// Οι δηλώσεις val είναι αμετάβλητες, ενώ οι var είναι μεταβλητές. +// Η αμεταβλητότητα είναι συμφέρουσα και προσπαθούμε να την χρησιμοποιούμε. +val x = 10 // το x είναι τώρα 10 +x = 20 // σφάλμα: αλλαγή σε val +var y = 10 +y = 20  // το y είναι τώρα 20 + +/* +  Η Scala είναι στατικού τύπου γλώσσα, εν τούτοις προσέξτε ότι στις παραπάνω +  δηλώσεις , δεν προσδιορίσαμε κάποιον τύπο. Αυτό συμβαίνει λόγω ενός +  χαρακτηριστικού της Scala που λέγεται συμπερασματολογία τύπων. Στις  +  περισσότερες των περιπτώσεων, ο μεταγλωττιστής της Scala μπορεί να +  μαντέψει ποιος είναι ο τύπος μιας μεταβλητής. Μπορούμε να δηλώσουμε +  αναλυτικά τον τύπο μιας μεταβλητής ως εξής: +*/ +val z: Int = 10 +val a: Double = 1.0 + +/* +  Προσέξτε ότι υπάρχει αυτόματη μετατροπή από ακέραιο (Int) σε διπλής  +  ακρίβειας (Double), και συνεπώς το αποτέλεσμα είναι 10.0 και όχι 10.  +*/  +val b: Double = 10 + +// Λογικές τιμές +true +false + +// Λογικές Πράξεις +!true // false +!false // true +true == false // false +10 > 5 // true + +// Η αριθμητική είναι όπως τα συνηθισμένα +1 + 1 // 2 +2 - 1 // 1 +5 * 3 // 15 +6 / 2 // 3 +6 / 4 // 1 +6.0 / 4 // 1.5 + + +/* +  Αξιολογώντας μια έκφραση στο REPL, σας δίνεται ο τύπος και  +  η τιμή του αποτελέσματος  +*/ + +1 + 7 + +/* Η παραπάνω γραμμή έχει το εξής αποτέλεσμα: + +  scala> 1 + 7 +  res29: Int = 8 + +  Αυτό σημαίνει ότι το αποτέλεσμα της αξιολόγησης του 1 + 7 είναι ένα αντικείμενο +  τύπου Int με τιμή 8 + +  Σημειώστε ότι το "res29" είναι ένα σειριακά δημιουργούμενο όνομα μεταβλητής +  για να αποθηκεύονται τα αποτελέσματα των εκφράσεων που έχετε πληκτρολογήσει  +  και συνεπώς η έξοδός σας μπορεί να διαφέρει. +*/ + +"Τα αλφαριθμητικά στην Scala περικλείονται από διπλά εισαγωγικά" +'a' // Ένας χαρακτήρας στην Scala +// res30: Char = a +// Αλφαριθημτικά με μονά εισαγωγικά δεν υφίστανται <= Αυτό θα προκαλέσει σφάλμα. + +// Τα αλφαριθμητικά έχουν τις συνηθισμένες μεθόδους της Java ορισμένες πάνω τους. +"hello world".length +"hello world".substring(2, 6) +"hello world".replace("C", "3") + +// Έχουν επίσης μερικές επιπλέον μεθόδους Scala.  +// Δείτε επίσης : scala.collection.immutable.StringOps +"hello world".take(5) +"hello world".drop(5) + +// Παρεμβολή αλφαριθμητικών : παρατηρήστε το πρόθεμα "s" +val n = 45 +s"We have $n apples" // => "We have 45 apples" + +// Παρατηρήστε την χρήση των '{', '}' +val a = Array(11, 9, 6) +s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old." +s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples." +s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4" + +// Μορφοποίηση με παρεμβεβλημένα αλφαριθμητικά με το πρόθεμα "f" +f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25" +f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454" + +// Raw αλφαριθμητικά, που αγνοούν τους ειδικούς χαρακτήρες. +raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r." + +// Μερικούς χαρακτήρες πρέπει να τους κάνουμε "escape", +// λ.χ ένα διπλό εισαγωγικό μέσα σε ένα αλφαριθμητικό : +"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown"" + +/*  +  Τα τριπλά διπλά-εισαγωγικά επιτρέπουν στα αλφαριθμητικά να εκτείνονται σε +  πολλαπλές γραμμές και να περιέχουν διπλά εισαγωγικά +*/ +val html = """<form id="daform"> +                <p>Press belo', Joe</p> +                <input type="submit"> +              </form>""" + + +///////////////////////////////////////////////// +// 2. Συναρτήσεις +///////////////////////////////////////////////// + +// Οι συναρτήσεις ορίζονται ως εξής: +// +//   def functionName(args...): ReturnType = { body... } +// +// Αν προέρχεστε απο πιο παραδοσιακές γλώσσες (C/C++ , Java) παρατηρήστε +// την παράλειψη του return. Στην Scala , η τελευταία έκφραση στο μπλόκ +// της συνάρτησης είναι η τιμή που επιστρέφει η συνάρτηση. +def sumOfSquares(x: Int, y: Int): Int = { +  val x2 = x * x +  val y2 = y * y +  x2 + y2 +} + +// Τα { } μπορούν να παραλειφθούν αν η συνάρτηση αποτελείται απο μια απλή έκφραση: +def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y + +// Η σύνταξη για την κλήση συναρτήσεων είναι γνώριμη: +sumOfSquares(3, 4)  // => 25 + +// Στις περισσότερες των περιπτώσεων (με τις αναδρομικές συναρτήσεις να αποτελούν +// την πιο αξιοπρόσεκτη εξαίρεση) , ο τύπος επιστροφής της συνάρτησης μπορεί να +// παραλειφθεί, και η ίδια συμπερασματολογία τύπων που είδαμε με τις μεταβλητές +// θα δουλεύει και με τους τύπους επιστροφής της συνάρτησης: +def sq(x: Int) = x * x  // Ο μεταγλωττιστής μπορεί να μαντέψει ότι +                        // ο τύπος επιστροφής της συνάρτησης είναι Int + +// Οι συναρτήσεις μπορούν να έχουν προκαθορισμένες τιμές: +def addWithDefault(x: Int, y: Int = 5) = x + y +addWithDefault(1, 2)  // => 3 +addWithDefault(1)  // => 6 + + +// Οι ανώνυμες συναρτήσεις είναι ως εξής: +(x:Int) => x * x + +// Σε αντίθεση με τα defs , ακόμα και ο τύπος εισόδου απο τις ανώνυμες +// συναρτήσεις μπορεί να παραληφθεί αν τα συμφραζόμενα το κάνουν ξεκάθαρο. +// Προσέξτε τον τύπο "Int => Int" που σημαίνει ότι μια συνάρτηση παίρνει +// ένα Int και επιστρέφει ένα Int. +val sq: Int => Int = x => x * x + +// Οι ανώνυμες συναρτήσεις μπορούν να κληθούν όπως συνήθως: +sq(10)   // => 100 + +// Αν κάθε όρισμα στην ανώνυμη συνάρτηση χρησιμοποιείται μόνο μία φορά, +// η Scala επιτρέπει έναν ακόμα πιο σύντομο τρόπο να οριστεί. Αυτές +// οι ανώνυμες συναρτήσεις αποδεικνύεται ότι είναι πολύ κοινές , +// όπως θα γίνει προφανές στο μέρος των δομών δεδομένων. +val addOne: Int => Int = _ + 1 +val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3) + +addOne(5)  // => 6 +weirdSum(2, 4)  // => 16 + +// Η δεσμευμένη λέξη return υπάρχει στην Scala , αλλά επιστρέφει μόνο  +// από το πιο εσωτερικό def που την περικλείει. +// ΠΡΟΣΟΧΗ: Η χρήση του return στην Scala είναι επιρρεπής σε λάθη +// και θα πρέπει να αποφεύγεται. +// Δεν έχει καμία επίδραση στις ανώνυμες συναρτήσεις. Για παράδειγμα:  +def foo(x: Int): Int = { +  val anonFunc: Int => Int = { z => +    if (z > 5) +      return z  // Αυτή η σειρά κάνει το z την τιμή που επιστρέφει η foo! +    else +      z + 2  // Αυτή η γραμμή είναι η τιμή που επιστρέφει η anonFunc +  } +  anonFunc(x)  // Αυτή η γραμμή είναι η τιμή που επιστρέφει η foo +} + + +///////////////////////////////////////////////// +// 3. Έλεγχος ροής +///////////////////////////////////////////////// + +1 to 5 +val r = 1 to 5 +r.foreach( println ) + +r foreach println +// ΠΡΟΣΟΧΗ: Η Scala είναι σχετικά επιεικής ως αναφορά τις τελείες και  +// τις παρενθέσεις. Διαβάστε τους κανόνες ξεχωριστά.  +// Αυτό βοηθάει στο να γράφεις DSLs και APIs που διαβάζονται σαν τα Αγγλικά. + +(5 to 1 by -1) foreach ( println ) + +// Ένας βρόχος while : +var i = 0 +while (i < 10) {  println("i " + i); i+=1  } + +while (i < 10) {  println("i " + i); i+=1  }   // Ναι ξανά! Τι συνέβη; Γιατί; + +i    // Εμφάνισε την τιμή του i. Σημειώστε ότι ένας βρόχος while είναι βρόχος +     // με την κλασική έννοια - εκτελείται σειριακά καθώς αλλάζει η μεταβλητή +     // του βρόχου. Το while είναι πολύ γρήγορο , γρηγορότερο απο τους βρόχους +     // της Java , αλλά η χρήση combinators και comprehensions όπως πιο πάνω , +     // είναι πιο εύκολη στην κατανόηση και στην παραλληλοποίηση. + +// Ένας βρόχος do while : +do { +  println("x is still less than 10"); +  x += 1 +} while (x < 10) + +// Η αναδρομή ουράς είναι ένας ιδιωματικός τρόπος να κάνεις επαναλαμβανόμενα +// πράγματα στην Scala. Οι αναδρομικές συναρτήσεις απαιτούν να γραφτεί  +// ρητά ο τύπος που θα επιστρέψουν, αλλιώς ο μεταγλωττιστής δεν μπορεί  +// αλλιώς να τον συνάγει. Παρακάτω είναι μια συνάρτηση που επιστρέφει Unit. +def showNumbersInRange(a:Int, b:Int):Unit = { +  print(a) +  if (a < b) +    showNumbersInRange(a + 1, b) +} +showNumbersInRange(1,14) + + +// Έλεγχος Ροής + +val x = 10 + +if (x == 1) println("yeah") +if (x == 10) println("yeah") +if (x == 11) println("yeah") +if (x == 11) println ("yeah") else println("nay") + +println(if (x == 10) "yeah" else "nope") +val text = if (x == 10) "yeah" else "nope" + + +///////////////////////////////////////////////// +// 4. Δομές Δεδομένων +///////////////////////////////////////////////// + +val a = Array(1, 2, 3, 5, 8, 13) +a(0) +a(3) +a(21)    // "Πετάει" exception + +val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") +m("fork") +m("spoon") +m("bottle")       // "Πετάει" exception + +val safeM = m.withDefaultValue("no lo se") +safeM("bottle") + +val s = Set(1, 3, 7) +s(0) +s(1) + +/* Δείτε το documentation του map εδώ - + * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map + */ + + +// Πλειάδες + +(1, 2) + +(4, 3, 2) + +(1, 2, "three") + +(a, 2, "three") + +// Γιατί να το έχουμε αυτό; +val divideInts = (x:Int, y:Int) => (x / y, x % y) + +divideInts(10,3) // Η συνάρτηση divideInts επιστρέφει το αποτέλεσμα  +                 // της ακέραιας διαίρεσης και το υπόλοιπο. + +// Για να έχουμε πρόσβαση στα στοιχεία μιας πλειάδας, χρησιμοποιούμε το _._n +// όπου το n είναι ο δείκτης με βάση το 1 του στοιχείου. +val d = divideInts(10,3) + +d._1 + +d._2 + + +///////////////////////////////////////////////// +// 5. Αντικειμενοστραφής Προγραμματισμός +///////////////////////////////////////////////// + +/* +  Ότι έχουμε κάνει ως τώρα σε αυτό το tutorial ήταν απλές εκφράσεις +  (τιμές, συναρτήσεις, κτλ.). Αυτές οι εκφράσεις βολεύουν όταν τις +  γράφουμε στο REPL για γρήγορες δοκιμές, αλλά δεν μπορούν να υπάρχουν +  από μόνες τους σε ένα αρχείο Scala. Για παράδειγμα , δεν μπορούμε να +  έχουμε μόνο ένα "val x = 5" στο αρχείο Scala. Αντί αυτού , τα μόνα +  στοιχεία του πάνω επιπέδου που επιτρέπονται στην Scala είναι: + +  - αντικείμενα (objects) +  - κλάσεις (classes) +  - κλάσεις περίπτωσης (case classes στην Scala) +  - Χαρακτηριστικά (traits , όπως ονομάζονται στην Scala) + +  Και τώρα θα εξηγήσουμε τι είναι αυτά. +*/ +// Οι κλάσεις είναι παρόμοιες με τις κλάσεις σε άλλες γλώσσες. Τα ορίσματα του +// "κατασκευαστή" (constructor) δηλώνονται μετά από το όνομα της κλάσης ,  +// και η αρχικοποιήση γίνεται μέσα στο σώμα της κλάσης. +class Dog(br: String) { +  // Κώδικας για τον "κατασκευαστή" +  var breed: String = br + +  // Ορίζεται μια μέθοδος bark , που επιστρέφει ένα αλφαριθμητικό +  def bark = "Woof, woof!" + +  // Οι τιμές και οι μέθοδοι είναι public εκτός αν χρησιμοποιήσουμε κάποια +  // απο τις λέξεις κλειδιά "protected" και "private" .  +  private def sleep(hours: Int) = +    println(s"I'm sleeping for $hours hours") + +  // Οι abstract μέθοδοι είναι απλά μέθοδοι χωρίς σώμα. Αν βγάζαμε +  // το σχόλιο απο την επόμενη γραμμή η κλάση Dog θα έπρεπε να  +  // δηλωθεί ως abstract class Dog(...) { ... } : +  // def chaseAfter(what: String): String +} + +val mydog = new Dog("greyhound") +println(mydog.breed) // => "greyhound" +println(mydog.bark) // => "Woof, woof!" + + +// Η λέξη "object" δημιουργεί ένα type ΚΑΙ ένα singleton instance αυτού. +// Είναι κοινό για τις κλάσεις στην Scala να έχουν ένα "συντροφικό object", +// όπου η συμπεριφορά για κάθε instance αιχμαλωτίζεται μέσα στις κλάσεις +// αυτές καθ' αυτές, αλλά η συμπρεριφορά που σχετίζεται με όλα τα instances  +// της κλάσης πάνε μέσα στο object. Η διαφορά είναι παρόμοια με τις +// μεθόδους κλάσεων σε σχέση με στατικές μεθόδους σε άλλες γλώσσες. +// Προσέξτε ότι τα objects και οι κλάσεις μπορούν να έχουν το ίδιο όνομα. +object Dog { +  def allKnownBreeds = List("pitbull", "shepherd", "retriever") +  def createDog(breed: String) = new Dog(breed) +} + +// Οι κλάσεις περίπτωσης (case classes) είναι που έχουν την επιπλέον  +// λειτουργικότητα ενσωματωμένη. Μιά συνήθης ερώτηση για αρχάριους στην +// Scala είναι πότε να χρησιμοποιούνται κλάσεις και πότε case κλάσεις. +// Γενικά οι κλάσεις τείνουν να εστιάζουν στην ενθυλάκωση, τον +// πολυμορφισμό και τη συμπεριφορά. Οι τιμές μέσα σε αυτές τις κλάσεις  +// τείνουν να είναι private , και μόνο οι μέθοδοι είναι εκτεθειμένες. +// Ο κύριος σκοπός των case classes είναι να κρατούν δεδομένα που είναι +// σταθερές(immutable). Συνήθως έχουν λίγες μεθόδους και οι μέθοδοι σπάνια +// έχουν παρενέργειες. +case class Person(name: String, phoneNumber: String) + +// Δημιουργία ενός instance. Παρατηρήστε ότι τα case classes  +// δεν χρειάζονται την λέξη "new" . +val george = Person("George", "1234") +val kate = Person("Kate", "4567") + +// Με τα case classes, παίρνεις μερικά προνόμια δωρεάν , όπως: +george.phoneNumber  // => "1234" + +// Ελέγχεται η ισότητα για κάθε πεδίο (δεν χρειάζεται να +// κάνουμε override στο .equals) +Person("George", "1234") == Person("Kate", "1236")  // => false + +// Έυκολος τρόπος να κάνουμε αντιγραφή. Δημιουργούμε έναν νέο geroge: +// otherGeorge == Person("george", "9876") +val otherGeorge = george.copy(phoneNumber = "9876") + +// Και πολλά άλλα. Τα case classes έχουν και αντιστοίχιση προτύπων  +// (pattern matching) δωρεάν, δείτε παρακάτω. + +// Τα χαρακτηριστικά (traits) έρχονται σε λίγο καιρό ! + +///////////////////////////////////////////////// +// 6. Αντιστοίχιση Προτύπων  +///////////////////////////////////////////////// + +// Η αντιστοίχιση προτύπων (pattern matching) είναι ένα πολύ δυνατό και +// ευρέως χρησιμοποιούμενο χαρακτηριστικό στην Scala. Παρακάτω βλέπουμε +// πως γίνεται το pattern matching σε ένα case class. Σημείωση: Σε  +// αντίθεση με άλλες γλώσσες η Scala δεν χρειάζεται breaks, γιατί γίνεται  +// αυτόματα όταν γίνει κάποιο match. + +def matchPerson(person: Person): String = person match { +  // Μετά προσδιορίζουμε το πρότυπο (pattern): +  case Person("George", number) => "We found George! His number is " + number +  case Person("Kate", number) => "We found Kate! Her number is " + number +  case Person(name, number) => "We matched someone : " + name + ", phone : " + number +} + +val email = "(.*)@(.*)".r  // Ορίζουμε ένα regex για το επόμενο παράδειγμα. +                           // (regex <- REGular EXpression)   + +// Το pattern matching μπορεί να μοιάζει γνώριμο απο τα switch statements σε +// γλώσσες που ανήκουν στην οικογένεια της C αλλά είναι πολύ πιο ισχυρό. +// Στην Scala , μπορούμε να κάνουμε match πολύ περισσότερα: +def matchEverything(obj: Any): String = obj match { +  // Μπορούμε να ταιριάξουμε τιμές: +  case "Hello world" => "Got the string Hello world" + +  // Μπορούμε να ταιριάξουμε τύπους: +  case x: Double => "Got a Double: " + x + +  // Μπορούμε να βάλουμε συνθήκες: +  case x: Int if x > 10000 => "Got a pretty big number!" + +  // Μπορούμε να ταιριάξουμε case classes όπως πρίν: +  case Person(name, number) => s"Got contact info for $name!" + +  // Μπορούμε να ταιριάξουμε regex: +  case email(name, domain) => s"Got email address $name@$domain" + +  // Μπορούμε να ταιριάξουμε πλειάδες: +  case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c" + +  // Μπορούμε να ταιριάξουμε δομές δεδομένων: +  case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c" + +  // Μπορούμε να ταιριάξουμε πρότυπα που το ένα είναι μέσα στο άλλο: +  case List(List((1, 2,"YAY"))) => "Got a list of list of tuple" +} + +// Στην πραγματικότητα , μπορούμε να κάνουμε pattern matching σε όποιο αντικείμενο +// έχει την μέθοδο "unapply". Αυτό το χαρακτηριστικό είναι τόσο ισχυρό ώστε +// η Scala επιτρέπει να ορίστούν ολόκληρες συναρτήσεις σαν patterns. +val patternFunc: Person => String = { +  case Person("George", number) => s"George's number: $number" +  case Person(name, number) => s"Random person's number: $number" +} + + +///////////////////////////////////////////////// +// 7. Συναρτησιακός Προγραμματισμός +///////////////////////////////////////////////// + +// Η Scala επιτρέπει στις μεθόδους και τις συναρτήσεις να επιστρέφουν ή να +// δέχονται ως παραμέτρους άλλες μεθόδους ή συναρτήσεις. + +val add10: Int => Int = _ + 10 // Μια συνάρτηση που δέχεται Int και επιστρέφει Int +List(1, 2, 3) map add10 // List(11, 12, 13) - το add10 εφαρμόζεται σε κάθε στοιχείο +                        // μέσω του map + +// Οι ανώνυμες συναρτήσεις μπορούν να χρησιμοποιηθούν αντί  +// ονοματισμένων (όπως απο πάνω) : +List(1, 2, 3) map (x => x + 10) + +// Και το σύμβολο της κάτω παύλας , μπορεί να χρησιμοποιηθεί αν υπάρχει μόνο +// ένα όρισμα στην ανώνυμη συνάρτηση. Έτσι δεσμεύεται ως η μεταβλητή. +List(1, 2, 3) map (_ + 10) + +// Αν το μπλοκ της ανώνυμης  συνάρτησης ΚΑΙ η συνάρτηση που εφαρμόζεται +// (στην περίπτωσή μας το foreach και το println) παίρνουν ένα όρισμα +// μπορείτε να παραλείψετε την κάτω παύλα. +List("Dom", "Bob", "Natalia") foreach println + + +// Συνδυαστές + +s.map(sq) + +val sSquared = s. map(sq) + +sSquared.filter(_ < 10) + +sSquared.reduce (_+_) + +// Η συνάρτηση filter παίρνει ένα κατηγορούμενο (predicate) +// που είναι μια συνάρτηση απο το A -> Boolean και διαλέγει  +// όλα τα στοιχεία που ικανοποιούν αυτό το κατηγορούμενο. +List(1, 2, 3) filter (_ > 2) // List(3) +case class Person(name:String, age:Int) +List( +  Person(name = "Dom", age = 23), +  Person(name = "Bob", age = 30) +).filter(_.age > 25) // List(Person("Bob", 30)) + + +// Το foreach είναι μια μέθοδος της Scala , που ορίζεται για ορισμένες +// συλλογές (collections). Παίρνει έναν τύπο και επιστρέφει Unit +// (μια μέθοδο void) +val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100) +aListOfNumbers foreach (x => println(x)) +aListOfNumbers foreach println + +// For comprehensions + +for { n <- s } yield sq(n) + +val nSquared2 = for { n <- s } yield sq(n) + +for { n <- nSquared2 if n < 10 } yield n + +for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared + +/* +  Προσοχή : Αυτά δεν ήταν βρόχοι for. Η σημασιολογία ενός βρόχου for είναι +  η επανάληψη, ενώ ένα for-comprehension ορίζει μια σχέση μεταξύ δύο +  συνόλων δεδομένων. +*/ + +///////////////////////////////////////////////// +// 8. Implicits +///////////////////////////////////////////////// +/* +  ΠΡΟΣΟΧΗ! Τα implicits είναι ένα σύνολο απο ισχυρά χαρακτηριστικά της Scala +  και επομένως είναι εύκολο να γίνει κατάχρηση. Οι αρχάριοι στην Scala θα  +  πρέπει να αντισταθούν στον πειρασμό να τα χρησιμοποιήσουν έως ότου, όχι  +  μόνο καταλάβουν πως λειτουργούν, αλλά ακόμα εξασκηθούν πάνω τους. +  Ο μόνος λόγος που συμπεριλάβαμε αυτό το κομμάτι στο tutorial είναι +  γιατί είναι τόσο κοινό στις βιβλιοθήκες της Scala , που αδύνατο να κάνεις  +  οτιδήποτε σημαντικό χωρίς να χρησιμοποιήσεις μια που να έχει implicits. + +*/ + +// Κάθε τιμή (vals , συναρτήσεις , αντικείμενα , κτλ) μπορεί να δηλωθεί ως +// implicit χρησιμοποιώντας , ναι το μαντέψατε , την λέξη "implicit". +// Σημειώστε ότι χρησιμοποιούμε την κλάση Dog που δημιουργήσαμε στο +// 5ο μέρος των παραδειγμάτων. +implicit val myImplicitInt = 100 +implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed) + + +// Απο μόνη της, η λέξη implicit, δεν αλλάζει την συμπεριφορά μιάς τιμής +// οπότε οι παραπάνω μπορούν να χρησιμοποιοηθούν όπως συνήθως. +myImplicitInt + 2  // => 102 +myImplicitFunction("Pitbull").breed  // => "Golden Pitbull" + +// Η διαφορά είναι ότι τώρα αυτές οι τιμές έχουν την δυνατότητα να  +// χρησιμοποιηθούν όταν ένα άλλο κομμάτι κώδικα "χρειάζεται" μια  +// implicit τιμή. Μια τέτοια περίπτωση είναι τα ορίσματα μιας implicit  +// συνάρτησης: +def sendGreetings(toWhom: String)(implicit howMany: Int) = +  s"Hello $toWhom, $howMany blessings to you and yours!" + +// Άν τροφοδοτήσουμε μια τιμή για το "homMany", η συνάρτηση συμπεριφέρεται +// ως συνήθως  +sendGreetings("John")(1000)  // => "Hello John, 1000 blessings to you and yours!" + +// Αλλά αν παραλείψουμε την παράμετρο implicit , μια implicit τιμή του ιδίου τύπου +// χρησιμοποιείται, στην περίπτωσή μας, το "myImplicitInt" +sendGreetings("Jane")  // => "Hello Jane, 100 blessings to you and yours!" + +// Οι παράμετροι implicit συναρτήσεων μας επιτρέπουν να προσομοιάζουμε +// κλάσεις τύπων (type classes) σε άλλες συναρτησιακές γλώσσες. +// Χρησιμοποιείται τόσο συχνά που έχει την δικιά του συντομογραφία. +// Οι επόμενες δύο γραμμές κώδικα σημαίνουν το ίδιο πράγμα. +def foo[T](implicit c: C[T]) = ... +def foo[T : C] = ... + + + +// Μια άλλη περίπτωση στην οποία ο μεταγλωττιστής αναζητά μια implicit τιμή  +// είναι αν έχετε obj.method (...) +// αλλά το "obj" δεν έχει την "method" ως μέθοδο. Σε αυτή την περίπτωση,  +// αν υπάρχει μια implicit μετατροπή του τύπου Α => Β, όπου Α είναι ο τύπος  +// του obj, ενώ το Β έχει μία μέθοδο που ονομάζεται «method», εφαρμόζεται η  +// εν λόγω μετατροπή. Έτσι, έχοντας την MyImplicitFunction μέσα στο πεδίο  +// εφαρμογής(scope), μπορούμε να πούμε: +"Retriever".breed  // => "Golden Retriever" +"Sheperd".bark  // => "Woof, woof!" + +// Εδώ το String αρχικά μετατρέπεται σε Dog χρησιμοποιώντας την συνάρτησή μας +// παραπάνω, και μετά καλείται η κατάλληλη μέθοδος. Αυτό είναι ένα εξερετικά +// ισχυρό χαρακτηριστικό, αλλά δεν πρέπει να χρησιμοποιείται με ελαφριά την  +// καρδιά. Μάλιστα, όταν ορίσατε την συνάρτηση implicit παραπάνω, ο μεταγλωττιστής +// θα πρέπει να σας έδωσε μια προειδοποιήση, ότι δεν πρέπει να το κάνετε αυτό  +// εκτός αν πραγματικά γνωρίζετε τι κάνετε. + + +///////////////////////////////////////////////// +// 9. Διάφορα +///////////////////////////////////////////////// + +// Εισαγωγή βιβλιοθηκών κτλ +import scala.collection.immutable.List + +// Εισαγωγή των πάντων απο το scala.collection.immutable +import scala.collection.immutable._ + +// Εισαγωγή πολλών κλάσεων σε μία έκφραση +import scala.collection.immutable.{List, Map} + +// Δώστε ένα νέο όνομα στην εισαγωγή σας χρησιμοποιώντας το '=>' +import scala.collection.immutable.{ List => ImmutableList } + +// Εισαγωγή όλων των κλάσεων εκτός απο μερικές. +// Το επόμενο δεν εισάγει το Map και το Set: +import scala.collection.immutable.{Map => _, Set => _, _} + +// Το σημείο εισαγωγής του προγράμματος σας ορίζεται σε ένα αρχείο scala , +// χρησιμοποιώντας ένα αντικείμενο (object), με μία μέθοδο , την main. +object Application { +  def main(args: Array[String]): Unit = { +    // Εδω γράφουμε ... +  } +} + +// Files can contain multiple classes and objects. Compile with scalac +// Τα files μπορούν να περιέχουν περισσότερες απο μία κλάσεις και  +// αντικείμενα. Το compile γίνεται με την εντολή scalac + +// Εισαγωγή και εξαγωγή. + +// Για να διβάσετε ένα αρχείο γραμμή προς γραμμή +import scala.io.Source +for(line <- Source.fromFile("myfile.txt").getLines()) +  println(line) + +// Για να γράψετε σε ένα αρχείο  +val writer = new PrintWriter("myfile.txt") +writer.write("Writing line for line" + util.Properties.lineSeparator) +writer.write("Another line here" + util.Properties.lineSeparator) +writer.close() + +``` + +## Further resources + +[Scala for the impatient](http://horstmann.com/scala/) + +[Twitter Scala school](http://twitter.github.io/scala_school/) + +[The scala documentation](http://docs.scala-lang.org/) + +[Try Scala in your browser](http://scalatutorials.com/tour/) + +Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user) + | 
