mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 09:41:36 +00:00
339 lines
17 KiB
Markdown
339 lines
17 KiB
Markdown
---
|
||
contributors:
|
||
- ["P1start", "http://p1start.github.io/"]
|
||
- ["Dimitri Kokkonis", "https://github.com/kokkonisd"]
|
||
filename: learnrust-gr.rs
|
||
---
|
||
|
||
_[ΣτΜ.: οι όροι "χαμηλό/υψηλό επίπεδο" αναφέρονται στην εγγύτητα μιας γλώσσας προγραμματισμού ή γενικότερα ενός
|
||
στοιχείου στην "μηχανή", ή το υλικό του υπολογιστή. Για παράδειγμα, η φράση "η C είναι μια γλώσσα χαμηλού επιπέδου"
|
||
αναφέρεται στο γεγονός ότι η C επιτρέπει άμεση και λεπτομερή διαχείρηση μνήμης, και πιο άμεσο έλεγχο του επεξεργαστή·
|
||
σε καμία περίπτωση δεν σημαίνει ότι η C έχει λιγότερες δυνατότητες, και γενικότερα δεν φέρει αρνητική σημασία.]_
|
||
|
||
Η Rust είναι μια γλώσσα προγραμματισμού ανεπτυγμένη από την Mozilla Research.
|
||
Συνδυάζει τον έλεγχο της απόδοσης χαμηλού επιπέδου με διευκολύνσεις και ασφάλεια υψηλού επιπέδου.
|
||
|
||
Πετυχαίνει αυτούς τους στόχους χωρίς να χρειάζεται garbage collector ή runtime, το οποίο καθιστά δυνατή τη χρήση
|
||
βιβλιοθηκών της Rust ως αντικατάσταση της C.
|
||
|
||
Η έκδοση 0.1 (η πρώτη της Rust) δημοσιεύθηκε τον Ιανουάριο του 2012, και για τα επόμενα 3 χρόνια η ανάπτυξή της
|
||
εξελίχθηκε τόσο γρήγορα που, μέχρι πρότινος, προτείνονταν η χρήση μη-σταθερών εκδόσεων (nightly builds) αντί σταθερών
|
||
εκδόσεων.
|
||
|
||
Τις 15 Μαΐου 2015 δημοσιεύτηκε η εκδοχή 1.0 της Rust, με πλήρη εγγύηση συμβατότητας με προηγούμενες εκδοχές. Οι
|
||
μη-σταθερές εκδόσεις συνήθως περιλαμβάνουν γρηγορότερους χρόνους μεταγλώττισης και γενικότερες βελτιώσεις όσον αφορά
|
||
τον μεταγλωττιστή. Η μέθοδος [train release](https://www.plutora.com/blog/agile-release-train) χρησιμοποιείται, με
|
||
συστηματικές εκδόσεις να δημοσιεύονται κάθε έξι εβδομάδες. Η beta έκδοση της Rust 1.1 δημοσιεύθηκε ταυτοχρόνως με την
|
||
σταθερή έκδοση 1.0.
|
||
|
||
Αν και η Rust είναι μια γλώσσα σχετικά χαμηλού επιπέδου, ο σχεδιασμός της περιλαμβάνει κάποιες έννοιες που συναντώνται
|
||
συνχότερα σε γλώσσες υψηλού επιπέδου. Αυτό καθιστά την Rust γρήγορη και αποδοτική αλλά επίσης εύκολη και προσβάσιμη.
|
||
|
||
|
||
```rust
|
||
// Αυτό είναι ένα σχόλιο. Τα σχόλια μίας γραμμής γράφονται έτσι...
|
||
// Και επεκτείνονται σε περισσότερες από μία γραμμές έτσι.
|
||
|
||
/// Τα σχόλια documentation γράφονται έτσι, και υποστηρίζουν markdown.
|
||
/// # Παράδειγμα
|
||
///
|
||
/// ```
|
||
/// let five = 5
|
||
/// ```
|
||
|
||
//////////////////////
|
||
// 1. Βασικές αρχές //
|
||
//////////////////////
|
||
|
||
#[allow(dead_code)]
|
||
// Συναρτήσεις
|
||
// `i32` είναι ο τύπος που αντιστοιχεί στους 32-bit signed ακέραιους
|
||
fn add2(x: i32, y: i32) -> i32 {
|
||
// Έμεσα εννοούμενη επιστροφή του αποτελέσματος, χωρίς semicolon (;)
|
||
x + y
|
||
}
|
||
|
||
#[allow(unused_variables)]
|
||
#[allow(unused_assignments)]
|
||
#[allow(dead_code)]
|
||
// Συνάρτηση main
|
||
fn main() {
|
||
// Αριθμοί //
|
||
|
||
// Αμετάβλητη δέσμευση (η τιμή που αντιστοιχεί στο όνομα "x" δεν μπορεί να αλλάξει)
|
||
let x: i32 = 1;
|
||
|
||
// Καταλήξεις integer/float
|
||
let y: i32 = 13i32;
|
||
let f: f64 = 1.3f64;
|
||
|
||
// Εξακρίβωση τύπου (type inference)
|
||
// Τις περισσότερες φορες ο μεταγλωττιστής της Rust μπορεί να εξακριβώσει τον τύπο μιας μεταβλητής, επομένως δεν
|
||
// χρειάζεται ο προγραμματιστής να τον δηλώνει ρητά.
|
||
// Σε αυτό το tutorial, οι τύποι δηλώνονται ρητά σε διάφορα σημεία, αλλά μόνο προκειμένου να είναι πιο ευανάγνωστος
|
||
// ο κώδικας. Ο μεταγλωττιστής μπορεί να το διαχειριστεί αυτόματα στις περισσότερες περιπτώσεις.
|
||
let implicit_x = 1;
|
||
let implicit_f = 1.3;
|
||
|
||
// Πράξεις
|
||
let sum = x + y + 13;
|
||
|
||
// Μεταβλητές (με την έννοια των προστακτικών γλωσσών προγραμματισμού).
|
||
// Στη Rust η αμετάβλητη δέσμευση είναι στάνταρ. Το mut δηλώνει μεταβλητότητα.
|
||
let mut mutable = 1;
|
||
mutable = 4;
|
||
mutable += 2;
|
||
|
||
// Αλφαριθμητικά //
|
||
|
||
// Σταθερά αλφαριθμητικά
|
||
let x: &str = "καλημέρα κόσμε!";
|
||
|
||
// Εκτύπωση αλφαριθμητικών
|
||
println!("{} {}", f, x); // 1.3 καλημέρα κόσμε!
|
||
|
||
// A `String` – a heap-allocated string
|
||
let s: String = "καλημέρα κόσμε".to_string();
|
||
|
||
// Ένα κομμάτι αλφαριθμητικού (string slice) – μια αμετάβλητη οπτική γωνία προς ένα άλλο αλφαριθμητικό
|
||
// Το αλφαριθμητικό μπορεί να είναι στατικό όπως τα σταθερά αλφαριθμητικά, ή να περιλαμβάνεται σε ένα άλλο,
|
||
// δυναμικό αντικείμενο (σε αυτή την περίπτωση τη μεταβλητή `s`)
|
||
let s_slice: &str = &s;
|
||
|
||
println!("{} {}", s, s_slice); // καλημέρα κόσμε καλημέρα κόσμε
|
||
|
||
// Διανύσματα/πίνακες //
|
||
|
||
// Πίνακας σταθερού μεγέθους
|
||
let four_ints: [i32; 4] = [1, 2, 3, 4];
|
||
|
||
// Δυναμικός πίνακας (διάνυσμα)
|
||
let mut vector: Vec<i32> = vec![1, 2, 3, 4];
|
||
vector.push(5);
|
||
|
||
// Ένα κομμάτι – μια αμετάβλητη οπτική γωνία προς ένα διάνυσμα ή πίνακα
|
||
// Είναι παρόμοιο με το κομμάτι αλφαριθμητικού που είδαμε προηγουμένως
|
||
let slice: &[i32] = &vector;
|
||
|
||
// Μπορούμε να χρησιμοποιήσουμε το `{:?}` για να εκτυπώσουμε κάτι σε στυλ debug
|
||
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
|
||
|
||
// Tuples (πλειάδες) //
|
||
|
||
// Ένα tuple είναι μια σταθερού μεγέθους σειρά από τιμές (πιθανά διαφορετικού τύπου)
|
||
let x: (i32, &str, f64) = (1, "καλημέρα", 3.4);
|
||
|
||
// Μπορούμε να χρησιμοποιήσουμε το `let` και ένα tuple για να δώσουμε πολλές τιμές σε πολλές μεταβλητές ταυτόχρονα
|
||
// (destructuring `let`)
|
||
let (a, b, c) = x;
|
||
println!("{} {} {}", a, b, c); // 1 καλημέρα 3.4
|
||
|
||
// Μπορούμε επίσης να επιλέξουμε ένα συγκεκριμένο στοιχείο από ένα tuple
|
||
println!("{}", x.1); // καλημέρα
|
||
|
||
//////////////
|
||
// 2. Τύποι //
|
||
//////////////
|
||
|
||
// Δομή
|
||
struct Point {
|
||
x: i32,
|
||
y: i32,
|
||
}
|
||
|
||
let origin: Point = Point { x: 0, y: 0 };
|
||
|
||
// Μια δομή με ανώνυμα πεδία, ή αλλιώς μια `δομή tuple` (`tuple struct`)
|
||
struct Point2(i32, i32);
|
||
|
||
let origin2 = Point2(0, 0);
|
||
|
||
// Enum, όπως στην C
|
||
enum Direction {
|
||
Left,
|
||
Right,
|
||
Up,
|
||
Down,
|
||
}
|
||
|
||
let up = Direction::Up;
|
||
|
||
// Enum με πεδία
|
||
enum OptionalI32 {
|
||
AnI32(i32),
|
||
Nothing,
|
||
}
|
||
|
||
let two: OptionalI32 = OptionalI32::AnI32(2);
|
||
let nothing = OptionalI32::Nothing;
|
||
|
||
// Γενικότητα (genericity) //
|
||
|
||
struct Foo<T> { bar: T }
|
||
|
||
// Αυτό ορίζεται στην standard library ως `Option`
|
||
enum Optional<T> {
|
||
SomeVal(T),
|
||
NoVal,
|
||
}
|
||
|
||
// Μέθοδοι //
|
||
|
||
impl<T> Foo<T> {
|
||
// Οι μέθοδοι παίρνουν πάντα μια ρητή παράμετρο `self`
|
||
fn bar(&self) -> &T { // Δανειζόμαστε το self
|
||
&self.bar
|
||
}
|
||
fn bar_mut(&mut self) -> &mut T { // Γίνεται "μεταβλητός δανεισμός" του self (μπορούμε να το τροποποιήσουμε)
|
||
&mut self.bar
|
||
}
|
||
fn into_bar(self) -> T { // Εδώ το self καταναλώνεται
|
||
self.bar
|
||
}
|
||
}
|
||
|
||
let a_foo = Foo { bar: 1 };
|
||
println!("{}", a_foo.bar()); // 1
|
||
|
||
// Χαρακτηρηστικά (traits) (γνωστά ως interfaces ή typeclasses σε άλλες γλώσσες) //
|
||
|
||
trait Frobnicate<T> {
|
||
fn frobnicate(self) -> Option<T>;
|
||
}
|
||
|
||
impl<T> Frobnicate<T> for Foo<T> {
|
||
fn frobnicate(self) -> Option<T> {
|
||
Some(self.bar)
|
||
}
|
||
}
|
||
|
||
let another_foo = Foo { bar: 1 };
|
||
println!("{:?}", another_foo.frobnicate()); // Some(1)
|
||
|
||
//////////////////////////////////////////////////
|
||
// 3. Αντιστοιχίσεις Μοτίβων (Pattern Matching) //
|
||
//////////////////////////////////////////////////
|
||
|
||
let foo = OptionalI32::AnI32(1);
|
||
match foo {
|
||
OptionalI32::AnI32(n) => println!("Είναι ένα i32: {}", n),
|
||
OptionalI32::Nothing => println!("Δεν είναι τίποτα!"),
|
||
}
|
||
|
||
// Προχωρημένο pattern matching
|
||
struct FooBar { x: i32, y: OptionalI32 }
|
||
let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) };
|
||
|
||
match bar {
|
||
FooBar { x: 0, y: OptionalI32::AnI32(0) } =>
|
||
println!("Οι αριθμοί είναι μηδέν!"),
|
||
FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m =>
|
||
println!("Οι αριθμοί είναι οι ίδιοι"),
|
||
FooBar { x: n, y: OptionalI32::AnI32(m) } =>
|
||
println!("Διαφορετικοί αριθμοί: {} {}", n, m),
|
||
FooBar { x: _, y: OptionalI32::Nothing } =>
|
||
println!("Ο δεύτερος αριθμός δεν είναι τίποτα!"),
|
||
}
|
||
|
||
/////////////////////
|
||
// 4. Έλεγχος ροής //
|
||
/////////////////////
|
||
|
||
// Βρόχοι `for`
|
||
let array = [1, 2, 3];
|
||
for i in array {
|
||
println!("{}", i);
|
||
}
|
||
|
||
// Διαστήματα
|
||
for i in 0u32..10 {
|
||
print!("{} ", i);
|
||
}
|
||
println!("");
|
||
// Τυπώνει `0 1 2 3 4 5 6 7 8 9 `
|
||
|
||
// `if` (υπό συνθήκη διακλάδωση)
|
||
if 1 == 1 {
|
||
println!("Τα μαθηματικά δουλεύουν!");
|
||
} else {
|
||
println!("Ωχ όχι...");
|
||
}
|
||
|
||
// `if` ως έκφραση
|
||
let value = if true {
|
||
"καλό"
|
||
} else {
|
||
"κακό"
|
||
};
|
||
|
||
// Βρόχοι `while`
|
||
while 1 == 1 {
|
||
println!("Το σύμπαν λειτουργεί κανονικά.");
|
||
// Μπορούμε να βγούμε από το βρόχο με το `break`
|
||
break
|
||
}
|
||
|
||
// Ατέρμονος βρόχος
|
||
loop {
|
||
println!("Καλημέρα!");
|
||
// Μπορούμε να βγούμε από το βρόχο με το `break`
|
||
break
|
||
}
|
||
|
||
//////////////////////////////////
|
||
// 5. Ασφάλεια μνήμης & δείκτες //
|
||
//////////////////////////////////
|
||
|
||
// Δείκτης με ιδιοκτήτη – μόνο ένα αντικείμενο μπορεί να είναι ο "ιδιοκτήτης" αυτού του δείκτη ανά πάσα στιγμή
|
||
// Αυτό σημαίνει ότι μόλις το `Box` βγει εκτός πλαισίου (out of scope), ο δείκτης μπορεί να ελευθερωθεί με ασφάλεια
|
||
let mut mine: Box<i32> = Box::new(3);
|
||
*mine = 5; // Dereference του δείκτη
|
||
// Εδώ, το `now_its_mine` γίνεται ιδιοκτήτης του `mine`. Δηλαδή, το `mine` μετακινείται.
|
||
let mut now_its_mine = mine;
|
||
*now_its_mine += 2;
|
||
|
||
println!("{}", now_its_mine); // 7
|
||
// println!("{}", mine); // Αυτό παράγει λάθος κατά τη μεταγλώττιση διότι τώρα ο δείκτης ανήκει στο `now_its_mine`
|
||
|
||
// Reference (αναφορά) – ένας αμετάβλητος δείκτης που αναφέρεται σε άλλα δεδομένα
|
||
// Όταν μια αναφορά δίνεται σε μια τιμή, λέμε πως η τιμή έχει "δανειστεί".
|
||
// Όταν μια τιμή δανείζεται αμετάβλητα, δεν μπορεί να είναι mutated (να μεταβληθεί) ή να μετακινηθεί.
|
||
// Ένας "δανεισμός" παραμένει ενεργός μέχρι την τελευταία χρήση της μεταβλητής που δανείζεται.
|
||
let mut var = 4;
|
||
var = 3;
|
||
let ref_var: &i32 = &var;
|
||
|
||
println!("{}", var); // Αντίθετα με το `mine` προηγουμένως, η μεταβλητή `var` μπορεί ακόμα να χρησιμοποιηθεί
|
||
println!("{}", *ref_var);
|
||
// var = 5; // Αυτό παράγει λάθος κατά τη μεταγλώττιση γιατί η μεταβλητή `var` είναι δανεισμένη
|
||
// *ref_var = 6; // Το ίδιο εδώ, γιατί η `ref_var` αποτελεί αμετάβλητη αναφορά
|
||
ref_var; // Εντολή no-op (τίποτα δεν εκτελείται από τον επεξεργαστή), η οποία όμως μετράει ως χρήση και κρατά τον
|
||
// "δανεισμό" ενεργό
|
||
var = 2; // Η `ref_var` δεν χρησιμοποιείται από εδώ και στο εξής, άρα ο "δανεισμός" τελειώνει
|
||
|
||
// Μεταβλητή αναφορά
|
||
// Όσο μια τιμή είναι μεταβλητά δανεισμένη, παραμένει τελείως απροσβάσιμη.
|
||
let mut var2 = 4;
|
||
let ref_var2: &mut i32 = &mut var2;
|
||
*ref_var2 += 2; // Ο αστερίσκος (*) χρησιμοποιείται ως δείκτης προς την μεταβλητά δανεισμένη `var2`
|
||
|
||
println!("{}", *ref_var2); // 6 , // Αν είχαμε `var2` εδώ θα προκαλούνταν λάθος μεταγλώττισης.
|
||
// O τύπος της `ref_var2` είναι &mut i32, άρα αποθηκεύει μια αναφορά προς μια τιμή i32, όχι την τιμή την ίδια.
|
||
// var2 = 2; // Λάθος μεταγλώττισης, γιατί η `var2` είναι δανεισμένη.
|
||
ref_var2; // Εντολή no-op (τίποτα δεν εκτελείται από τον επεξεργαστή), η οποία όμως μετράει ως χρήση και κρατά τον
|
||
// "δανεισμό" ενεργό
|
||
}
|
||
```
|
||
|
||
## Μάθετε περισσότερα
|
||
|
||
Υπάρχουν πολλά ακόμα πράγματα να μάθει κανείς· αυτά είναι μόνο τα βασικά της Rust, που επιτρέπουν να καταλάβουμε το
|
||
βασικό τρόπο λειτουργίας της. Για να μάθετε περισσότερα για τη Rust, διαβάστε το [The Rust Programming
|
||
Language](http://doc.rust-lang.org/book/index.html) και επισκεφθείτε το subreddit [/r/rust](http://reddit.com/r/rust).
|
||
Οι άνθρωποι πίσω από το κανάλι #rust στο irc.mozilla.org είναι επίσης πάντα πρόθυμοι να βοηθήσουν τους αρχάριους.
|
||
|
||
Μπορείτε επίσης να παίξετε με τη Rust χρησιμοποιώντας τους εξής online μεταγλωττιστές:
|
||
|
||
- [Rust Playground](https://play.rust-lang.org)
|
||
- [Rust website](http://rust-lang.org)
|