mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2025-04-27 15:43:58 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
eb7e58d5fc
@ -159,11 +159,12 @@ void foo()
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Assume everything is from the namespace "Second"
|
// Includes all symbols from `namesapce Second` into the current scope. Note
|
||||||
// unless otherwise specified.
|
// that simply `foo()` no longer works, since it is now ambiguous whether
|
||||||
|
// we're calling the `foo` in `namespace Second` or the top level.
|
||||||
using namespace Second;
|
using namespace Second;
|
||||||
|
|
||||||
foo(); // prints "This is Second::foo"
|
Second::foo(); // prints "This is Second::foo"
|
||||||
First::Nested::foo(); // prints "This is First::Nested::foo"
|
First::Nested::foo(); // prints "This is First::Nested::foo"
|
||||||
::foo(); // prints "This is global foo"
|
::foo(); // prints "This is global foo"
|
||||||
}
|
}
|
||||||
|
1103
chapel.html.markdown
Normal file
1103
chapel.html.markdown
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
language: yaml
|
language: yaml
|
||||||
filename: learnyaml.yaml
|
|
||||||
contributors:
|
contributors:
|
||||||
- ["Adam Brenecki", "https://github.com/adambrenecki"]
|
- ["Adam Brenecki", "https://github.com/adambrenecki"]
|
||||||
translators:
|
translators:
|
||||||
- ["Ruben M.", https://github.com/switchhax]
|
- ["Ruben M.", "https://github.com/switchhax"]
|
||||||
|
filename: learnyaml-de.yaml
|
||||||
|
lang: de-de
|
||||||
---
|
---
|
||||||
|
|
||||||
YAML ist eine Sprache zur Datenserialisierung, die sofort von Menschenhand geschrieben und gelesen werden kann.
|
YAML ist eine Sprache zur Datenserialisierung, die sofort von Menschenhand geschrieben und gelesen werden kann.
|
||||||
|
745
el-gr/racket-gr.html.markdown
Normal file
745
el-gr/racket-gr.html.markdown
Normal file
@ -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/)
|
689
el-gr/scala-gr.html.markdown
Normal file
689
el-gr/scala-gr.html.markdown
Normal file
@ -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)
|
||||||
|
|
@ -195,7 +195,7 @@ cond do
|
|||||||
"But I will"
|
"But I will"
|
||||||
end
|
end
|
||||||
|
|
||||||
# It is common to see the last condition equal to `true`, which will always match.
|
# It is common to set the last condition equal to `true`, which will always match.
|
||||||
cond do
|
cond do
|
||||||
1 + 1 == 3 ->
|
1 + 1 == 3 ->
|
||||||
"I will never be seen"
|
"I will never be seen"
|
||||||
|
@ -38,7 +38,7 @@ uno o varios archivos, a lo largo del tiempo.
|
|||||||
* Se puede trabajar sin conexion.
|
* Se puede trabajar sin conexion.
|
||||||
* Colaborar con otros es sencillo!.
|
* Colaborar con otros es sencillo!.
|
||||||
* Derivar, Crear ramas del proyecto (aka: Branching) es facil!.
|
* Derivar, Crear ramas del proyecto (aka: Branching) es facil!.
|
||||||
* Combinar (aka: Marging)
|
* Combinar (aka: Merging)
|
||||||
* Git es rapido.
|
* Git es rapido.
|
||||||
* Git es flexible.
|
* Git es flexible.
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ contributors:
|
|||||||
- ["Louie Dinh", "http://ldinh.ca"]
|
- ["Louie Dinh", "http://ldinh.ca"]
|
||||||
translators:
|
translators:
|
||||||
- ["Camilo Garrido", "http://www.twitter.com/hirohope"]
|
- ["Camilo Garrido", "http://www.twitter.com/hirohope"]
|
||||||
|
- ["Fabio Souto", "http://fabiosouto.me"]
|
||||||
lang: es-es
|
lang: es-es
|
||||||
filename: learnpython-es.py
|
filename: learnpython-es.py
|
||||||
---
|
---
|
||||||
@ -30,27 +31,47 @@ Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser apl
|
|||||||
# Tienes números
|
# Tienes números
|
||||||
3 #=> 3
|
3 #=> 3
|
||||||
|
|
||||||
# Matemática es lo que esperarías
|
# Evidentemente puedes realizar operaciones matemáticas
|
||||||
1 + 1 #=> 2
|
1 + 1 #=> 2
|
||||||
8 - 1 #=> 7
|
8 - 1 #=> 7
|
||||||
10 * 2 #=> 20
|
10 * 2 #=> 20
|
||||||
35 / 5 #=> 7
|
35 / 5 #=> 7
|
||||||
|
|
||||||
# La división es un poco complicada. Es división entera y toma la parte entera
|
# La división es un poco complicada. Es división entera y toma la parte entera
|
||||||
# de los resultados automáticamente.
|
# de los resultados automáticamente.
|
||||||
5 / 2 #=> 2
|
5 / 2 #=> 2
|
||||||
|
|
||||||
# Para arreglar la división necesitamos aprender sobre 'floats'
|
# Para arreglar la división necesitamos aprender sobre 'floats'
|
||||||
# (números de coma flotante).
|
# (números de coma flotante).
|
||||||
2.0 # Esto es un 'float'
|
2.0 # Esto es un 'float'
|
||||||
11.0 / 4.0 #=> 2.75 ahhh...mucho mejor
|
11.0 / 4.0 #=> 2.75 ahhh...mucho mejor
|
||||||
|
|
||||||
|
# Resultado de la división de enteros truncada para positivos y negativos
|
||||||
|
5 // 3 # => 1
|
||||||
|
5.0 // 3.0 # => 1.0 # funciona con números en coma flotante
|
||||||
|
-5 // 3 # => -2
|
||||||
|
-5.0 // 3.0 # => -2.0
|
||||||
|
|
||||||
|
# El operador módulo devuelve el resto de una división entre enteros
|
||||||
|
7 % 3 # => 1
|
||||||
|
|
||||||
|
# Exponenciación (x elevado a y)
|
||||||
|
2**4 # => 16
|
||||||
|
|
||||||
# Refuerza la precedencia con paréntesis
|
# Refuerza la precedencia con paréntesis
|
||||||
(1 + 3) * 2 #=> 8
|
(1 + 3) * 2 #=> 8
|
||||||
|
|
||||||
# Valores 'boolean' (booleanos) son primitivos
|
# Operadores booleanos
|
||||||
True
|
# Nota: "and" y "or" son sensibles a mayúsculas
|
||||||
False
|
True and False #=> False
|
||||||
|
False or True #=> True
|
||||||
|
|
||||||
|
# Podemos usar operadores booleanos con números enteros
|
||||||
|
0 and 2 #=> 0
|
||||||
|
-5 or 0 #=> -5
|
||||||
|
0 == False #=> True
|
||||||
|
2 == True #=> False
|
||||||
|
1 == True #=> True
|
||||||
|
|
||||||
# Niega con 'not'
|
# Niega con 'not'
|
||||||
not True #=> False
|
not True #=> False
|
||||||
@ -90,7 +111,7 @@ not False #=> True
|
|||||||
# Una forma más reciente de formatear strings es el método 'format'.
|
# Una forma más reciente de formatear strings es el método 'format'.
|
||||||
# Este método es la forma preferida
|
# Este método es la forma preferida
|
||||||
"{0} pueden ser {1}".format("strings", "formateados")
|
"{0} pueden ser {1}".format("strings", "formateados")
|
||||||
# Puedes usar palabras claves si no quieres contar.
|
# Puedes usar palabras clave si no quieres contar.
|
||||||
"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña")
|
"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña")
|
||||||
|
|
||||||
# None es un objeto
|
# None es un objeto
|
||||||
@ -107,8 +128,8 @@ None is None #=> True
|
|||||||
|
|
||||||
# None, 0, y strings/listas vacíos(as) todas se evalúan como False.
|
# None, 0, y strings/listas vacíos(as) todas se evalúan como False.
|
||||||
# Todos los otros valores son True
|
# Todos los otros valores son True
|
||||||
0 == False #=> True
|
bool(0) #=> False
|
||||||
"" == False #=> True
|
bool("") #=> False
|
||||||
|
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
@ -130,16 +151,16 @@ otra_variable # Levanta un error de nombre
|
|||||||
# 'if' puede ser usado como una expresión
|
# 'if' puede ser usado como una expresión
|
||||||
"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
|
"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
|
||||||
|
|
||||||
# Listas almacenan secuencias
|
# Las listas almacenan secuencias
|
||||||
lista = []
|
lista = []
|
||||||
# Puedes empezar con una lista prellenada
|
# Puedes empezar con una lista prellenada
|
||||||
otra_lista = [4, 5, 6]
|
otra_lista = [4, 5, 6]
|
||||||
|
|
||||||
# Añadir cosas al final de una lista con 'append'
|
# Añadir cosas al final de una lista con 'append'
|
||||||
lista.append(1) #lista ahora es [1]
|
lista.append(1) # lista ahora es [1]
|
||||||
lista.append(2) #lista ahora es [1, 2]
|
lista.append(2) # lista ahora es [1, 2]
|
||||||
lista.append(4) #lista ahora es [1, 2, 4]
|
lista.append(4) # lista ahora es [1, 2, 4]
|
||||||
lista.append(3) #lista ahora es [1, 2, 4, 3]
|
lista.append(3) # lista ahora es [1, 2, 4, 3]
|
||||||
# Remueve del final de la lista con 'pop'
|
# Remueve del final de la lista con 'pop'
|
||||||
lista.pop() #=> 3 y lista ahora es [1, 2, 4]
|
lista.pop() #=> 3 y lista ahora es [1, 2, 4]
|
||||||
# Pongámoslo de vuelta
|
# Pongámoslo de vuelta
|
||||||
@ -173,11 +194,11 @@ lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6]
|
|||||||
# Chequea la existencia en una lista con
|
# Chequea la existencia en una lista con
|
||||||
1 in lista #=> True
|
1 in lista #=> True
|
||||||
|
|
||||||
# Examina el largo de una lista con 'len'
|
# Examina el tamaño de una lista con 'len'
|
||||||
len(lista) #=> 6
|
len(lista) #=> 6
|
||||||
|
|
||||||
|
|
||||||
# Tuplas son como listas pero son inmutables.
|
# Las tuplas son como las listas, pero son inmutables.
|
||||||
tupla = (1, 2, 3)
|
tupla = (1, 2, 3)
|
||||||
tupla[0] #=> 1
|
tupla[0] #=> 1
|
||||||
tupla[0] = 3 # Levanta un error TypeError
|
tupla[0] = 3 # Levanta un error TypeError
|
||||||
@ -266,7 +287,7 @@ conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6}
|
|||||||
# Hagamos sólo una variable
|
# Hagamos sólo una variable
|
||||||
una_variable = 5
|
una_variable = 5
|
||||||
|
|
||||||
# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python!
|
# Aquí está una declaración de un 'if'. ¡La indentación es importante en Python!
|
||||||
# imprime "una_variable es menor que 10"
|
# imprime "una_variable es menor que 10"
|
||||||
if una_variable > 10:
|
if una_variable > 10:
|
||||||
print "una_variable es completamente mas grande que 10."
|
print "una_variable es completamente mas grande que 10."
|
||||||
@ -400,12 +421,12 @@ class Humano(object):
|
|||||||
# Un atributo de clase es compartido por todas las instancias de esta clase
|
# Un atributo de clase es compartido por todas las instancias de esta clase
|
||||||
especie = "H. sapiens"
|
especie = "H. sapiens"
|
||||||
|
|
||||||
# Constructor basico
|
# Constructor básico, se llama al instanciar la clase.
|
||||||
def __init__(self, nombre):
|
def __init__(self, nombre):
|
||||||
# Asigna el argumento al atributo nombre de la instancia
|
# Asigna el argumento al atributo nombre de la instancia
|
||||||
self.nombre = nombre
|
self.nombre = nombre
|
||||||
|
|
||||||
# Un metodo de instancia. Todos los metodos toman self como primer argumento
|
# Un método de instancia. Todos los metodos toman self como primer argumento
|
||||||
def decir(self, msg):
|
def decir(self, msg):
|
||||||
return "%s: %s" % (self.nombre, msg)
|
return "%s: %s" % (self.nombre, msg)
|
||||||
|
|
||||||
@ -470,6 +491,56 @@ import math
|
|||||||
dir(math)
|
dir(math)
|
||||||
|
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## 7. Avanzado
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
# Los generadores permiten evaluación perezosa
|
||||||
|
def duplicar_numeros(iterable):
|
||||||
|
for i in iterable:
|
||||||
|
yield i + i
|
||||||
|
|
||||||
|
# Un generador crea valores sobre la marcha
|
||||||
|
# En vez de generar y devolver todos los valores de una vez, crea un valor
|
||||||
|
# en cada iteración. En este ejemplo los valores mayores que 15 no serán
|
||||||
|
# procesados en duplicar_numeros.
|
||||||
|
# Nota: xrange es un generador que hace lo mismo que range.
|
||||||
|
# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio.
|
||||||
|
# xrange crea un generador, mientras que range crea toda la lista.
|
||||||
|
# Añadimos un guion bajo a los nombres de variable que coinciden con palabras
|
||||||
|
# reservadas de python.
|
||||||
|
xrange_ = xrange(1, 900000000)
|
||||||
|
|
||||||
|
# duplica todos los números hasta que encuentra un resultado >= 30
|
||||||
|
for i in duplicar_numeros(xrange_):
|
||||||
|
print i
|
||||||
|
if i >= 30:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Decoradores
|
||||||
|
# en este ejemplo pedir rodea a hablar
|
||||||
|
# Si por_favor es True se cambiará el mensaje.
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
|
def pedir(target_function):
|
||||||
|
@wraps(target_function)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
msg, por_favor = target_function(*args, **kwargs)
|
||||||
|
if por_favor:
|
||||||
|
return "{} {}".format(msg, "¡Por favor! Soy pobre :(")
|
||||||
|
return msg
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@pedir
|
||||||
|
def hablar(por_favor=False):
|
||||||
|
msg = "¿Me puedes comprar una cerveza?"
|
||||||
|
return msg, por_favor
|
||||||
|
|
||||||
|
print hablar() # ¿Me puedes comprar una cerveza?
|
||||||
|
print hablar(por_favor=True) # ¿Me puedes comprar una cerveza? ¡Por favor! Soy pobre :(
|
||||||
```
|
```
|
||||||
|
|
||||||
## ¿Listo para más?
|
## ¿Listo para más?
|
||||||
@ -481,6 +552,7 @@ dir(math)
|
|||||||
* [The Official Docs](http://docs.python.org/2.6/)
|
* [The Official Docs](http://docs.python.org/2.6/)
|
||||||
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
||||||
* [Python Module of the Week](http://pymotw.com/2/)
|
* [Python Module of the Week](http://pymotw.com/2/)
|
||||||
|
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
|
||||||
|
|
||||||
### Encuadernados
|
### Encuadernados
|
||||||
|
|
||||||
|
@ -434,9 +434,9 @@ les librairies standard:
|
|||||||
|
|
||||||
Autres références complémentaires:
|
Autres références complémentaires:
|
||||||
|
|
||||||
* <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">Lua for programmers</a>
|
* <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">Lua pour programmeurs</a>
|
||||||
* <a href="lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Courte de référence de Lua</a>
|
* <a href="lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Référence condensée de Lua</a>
|
||||||
* <a href="http://www.lua.org/pil/contents.html">Programming In Lua</a>
|
* <a href="http://www.lua.org/pil/contents.html">Programmer en Lua</a>
|
||||||
* <a href="http://www.lua.org/manual/">Les manuels de référence Lua</a>
|
* <a href="http://www.lua.org/manual/">Les manuels de référence Lua</a>
|
||||||
|
|
||||||
A propos, ce fichier est exécutable. Sauvegardez-le sous le nom *learn.lua* et
|
A propos, ce fichier est exécutable. Sauvegardez-le sous le nom *learn.lua* et
|
||||||
@ -446,4 +446,4 @@ Ce tutoriel a été originalement écrit pour <a href="tylerneylon.com">tylerney
|
|||||||
disponible en tant que <a href="https://gist.github.com/tylerneylon/5853042">gist</a>.
|
disponible en tant que <a href="https://gist.github.com/tylerneylon/5853042">gist</a>.
|
||||||
Il a été traduit en français par Roland Yonaba (voir son <a href="http://github.com/Yonaba">github</a>).
|
Il a été traduit en français par Roland Yonaba (voir son <a href="http://github.com/Yonaba">github</a>).
|
||||||
|
|
||||||
Amusez-vous bien avec Lua!
|
Amusez-vous bien avec Lua!
|
||||||
|
@ -209,14 +209,15 @@ foo 5 -- 75
|
|||||||
-- the expression on its right is applied as the parameter to the function on its left.
|
-- the expression on its right is applied as the parameter to the function on its left.
|
||||||
|
|
||||||
-- before
|
-- before
|
||||||
(even (fib 7)) -- false
|
even (fib 7) -- false
|
||||||
|
|
||||||
-- after
|
|
||||||
even . fib $ 7 -- false
|
|
||||||
|
|
||||||
-- equivalently
|
-- equivalently
|
||||||
even $ fib 7 -- false
|
even $ fib 7 -- false
|
||||||
|
|
||||||
|
-- composing functions
|
||||||
|
even . fib $ 7 -- false
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
-- 5. Type signatures
|
-- 5. Type signatures
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
language: c++
|
language: c++
|
||||||
filename: learncpp.cpp
|
filename: learncpp-it.cpp
|
||||||
contributors:
|
contributors:
|
||||||
- ["Steven Basart", "http://github.com/xksteven"]
|
- ["Steven Basart", "http://github.com/xksteven"]
|
||||||
- ["Matt Kline", "https://github.com/mrkline"]
|
- ["Matt Kline", "https://github.com/mrkline"]
|
||||||
|
@ -43,7 +43,7 @@ edit('myfunction.m') % Open function/script in editor
|
|||||||
type('myfunction.m') % Print the source of function/script to Command Window
|
type('myfunction.m') % Print the source of function/script to Command Window
|
||||||
|
|
||||||
profile on % turns on the code profiler
|
profile on % turns on the code profiler
|
||||||
profile of % turns off the code profiler
|
profile off % turns off the code profiler
|
||||||
profile viewer % Open profiler
|
profile viewer % Open profiler
|
||||||
|
|
||||||
help command % Displays documentation for command in Command Window
|
help command % Displays documentation for command in Command Window
|
||||||
|
@ -415,7 +415,7 @@ distance = 18; // References "long distance" from MyClass implementation
|
|||||||
|
|
||||||
+ (NSString *)classMethod
|
+ (NSString *)classMethod
|
||||||
{
|
{
|
||||||
return [[self alloc] init];
|
return @"Some string";
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
|
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
|
||||||
|
@ -12,16 +12,16 @@ Perl 5 is a highly capable, feature-rich programming language with over 25 years
|
|||||||
Perl 5 runs on over 100 platforms from portables to mainframes and is suitable for both rapid prototyping and large scale development projects.
|
Perl 5 runs on over 100 platforms from portables to mainframes and is suitable for both rapid prototyping and large scale development projects.
|
||||||
|
|
||||||
```perl
|
```perl
|
||||||
# Single line comments start with a number symbol.
|
# Single line comments start with a number sign.
|
||||||
|
|
||||||
|
|
||||||
#### Perl variable types
|
#### Perl variable types
|
||||||
|
|
||||||
# Variables begin with the $ symbol.
|
# Variables begin with a sigil, which is a symbol showing the type.
|
||||||
# A valid variable name starts with a letter or underscore,
|
# A valid variable name starts with a letter or underscore,
|
||||||
# followed by any number of letters, numbers, or underscores.
|
# followed by any number of letters, numbers, or underscores.
|
||||||
|
|
||||||
### Perl has three main variable types: scalars, arrays, and hashes.
|
### Perl has three main variable types: $scalar, @array, and %hash.
|
||||||
|
|
||||||
## Scalars
|
## Scalars
|
||||||
# A scalar represents a single value:
|
# A scalar represents a single value:
|
||||||
|
@ -7,10 +7,13 @@ contributors:
|
|||||||
- ["Nami-Doc", "http://github.com/Nami-Doc"]
|
- ["Nami-Doc", "http://github.com/Nami-Doc"]
|
||||||
---
|
---
|
||||||
|
|
||||||
Perl 6 is a highly capable, feature-rich programming language made for the
|
Perl 6 is a highly capable, feature-rich programming language made for at
|
||||||
upcoming hundred years.
|
least the next hundred years.
|
||||||
|
|
||||||
Perl 6 runs on [the MoarVM](http://moarvm.com) and the JVM.
|
The primary Perl 6 compiler is called [Rakudo](http://rakudo.org), which runs on
|
||||||
|
the JVM and [the MoarVM](http://moarvm.com) and
|
||||||
|
[prior to March 2015](http://pmthium.com/2015/02/suspending-rakudo-parrot/),
|
||||||
|
[the Parrot VM](http://parrot.org/).
|
||||||
|
|
||||||
Meta-note : the triple pound signs are here to denote headlines,
|
Meta-note : the triple pound signs are here to denote headlines,
|
||||||
double paragraphs, and single notes.
|
double paragraphs, and single notes.
|
||||||
@ -210,7 +213,7 @@ say $x; #=> 52
|
|||||||
# - `if`
|
# - `if`
|
||||||
# Before talking about `if`, we need to know which values are "Truthy"
|
# Before talking about `if`, we need to know which values are "Truthy"
|
||||||
# (represent True), and which are "Falsey" (or "Falsy") -- represent False.
|
# (represent True), and which are "Falsey" (or "Falsy") -- represent False.
|
||||||
# Only these values are Falsey: (), 0, "", Nil, A type (like `Str` or `Int`),
|
# Only these values are Falsey: (), "", Nil, A type (like `Str` or `Int`),
|
||||||
# and of course False itself.
|
# and of course False itself.
|
||||||
# Every other value is Truthy.
|
# Every other value is Truthy.
|
||||||
if True {
|
if True {
|
||||||
@ -1041,7 +1044,7 @@ postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that)
|
|||||||
# *everything* -- with great power comes great responsibility)
|
# *everything* -- with great power comes great responsibility)
|
||||||
|
|
||||||
## Meta operators !
|
## Meta operators !
|
||||||
# Oh boy, get ready. Get ready, because we're dwelving deep
|
# Oh boy, get ready. Get ready, because we're delving deep
|
||||||
# into the rabbit's hole, and you probably won't want to go
|
# into the rabbit's hole, and you probably won't want to go
|
||||||
# back to other languages after reading that.
|
# back to other languages after reading that.
|
||||||
# (I'm guessing you don't want to already at that point).
|
# (I'm guessing you don't want to already at that point).
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
language: xml
|
language: xml
|
||||||
filename: learnxml.xml
|
filename: learnxml-pt.xml
|
||||||
contributors:
|
contributors:
|
||||||
- ["João Farias", "https://github.com/JoaoGFarias"]
|
- ["João Farias", "https://github.com/JoaoGFarias"]
|
||||||
translators:
|
translators:
|
||||||
- ["Miguel Araújo", "https://github.com/miguelarauj1o"]
|
- ["Miguel Araújo", "https://github.com/miguelarauj1o"]
|
||||||
lang: pt-br
|
lang: pt-br
|
||||||
@ -130,4 +130,4 @@ com a adição de definição DTD.-->
|
|||||||
<preco>30.00</preco>
|
<preco>30.00</preco>
|
||||||
</livro>
|
</livro>
|
||||||
</livraria>
|
</livraria>
|
||||||
```
|
```
|
||||||
|
@ -327,8 +327,8 @@ prints:
|
|||||||
mouse is a mammal
|
mouse is a mammal
|
||||||
"""
|
"""
|
||||||
for animal in ["dog", "cat", "mouse"]:
|
for animal in ["dog", "cat", "mouse"]:
|
||||||
# You can use % to interpolate formatted strings
|
# You can use {0} to interpolate formatted strings. (See above.)
|
||||||
print "%s is a mammal" % animal
|
print "{0} is a mammal".format(animal)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
"range(number)" returns a list of numbers
|
"range(number)" returns a list of numbers
|
||||||
@ -387,7 +387,7 @@ else: # Optional clause to the try/except block. Must follow all except blocks
|
|||||||
|
|
||||||
# Use "def" to create new functions
|
# Use "def" to create new functions
|
||||||
def add(x, y):
|
def add(x, y):
|
||||||
print "x is %s and y is %s" % (x, y)
|
print "x is {0} and y is {1}".format(x, y)
|
||||||
return x + y # Return values with a return statement
|
return x + y # Return values with a return statement
|
||||||
|
|
||||||
# Calling functions with parameters
|
# Calling functions with parameters
|
||||||
@ -497,7 +497,7 @@ class Human(object):
|
|||||||
|
|
||||||
# An instance method. All methods take "self" as the first argument
|
# An instance method. All methods take "self" as the first argument
|
||||||
def say(self, msg):
|
def say(self, msg):
|
||||||
return "%s: %s" % (self.name, msg)
|
return "{0}: {1}".format(self.name, msg)
|
||||||
|
|
||||||
# A class method is shared among all instances
|
# A class method is shared among all instances
|
||||||
# They are called with the calling class as the first argument
|
# They are called with the calling class as the first argument
|
||||||
@ -624,16 +624,17 @@ print say(say_please=True) # Can you buy me a beer? Please! I am poor :(
|
|||||||
|
|
||||||
### Free Online
|
### Free Online
|
||||||
|
|
||||||
|
* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
|
||||||
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
|
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
|
||||||
* [Dive Into Python](http://www.diveintopython.net/)
|
* [Dive Into Python](http://www.diveintopython.net/)
|
||||||
* [The Official Docs](http://docs.python.org/2.6/)
|
* [The Official Docs](http://docs.python.org/2.6/)
|
||||||
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
||||||
* [Python Module of the Week](http://pymotw.com/2/)
|
* [Python Module of the Week](http://pymotw.com/2/)
|
||||||
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
|
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
|
||||||
|
* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
|
||||||
|
|
||||||
### Dead Tree
|
### Dead Tree
|
||||||
|
|
||||||
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
|
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
|
||||||
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
|
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
|
||||||
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
|
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
|
||||||
|
|
||||||
|
@ -394,15 +394,15 @@ our_iterable[1] # Raises a TypeError
|
|||||||
our_iterator = iter(our_iterable)
|
our_iterator = iter(our_iterable)
|
||||||
|
|
||||||
# Our iterator is an object that can remember the state as we traverse through it.
|
# Our iterator is an object that can remember the state as we traverse through it.
|
||||||
# We get the next object by calling the __next__ function.
|
# We get the next object with "next()".
|
||||||
our_iterator.__next__() #=> "one"
|
next(our_iterator) #=> "one"
|
||||||
|
|
||||||
# It maintains state as we call __next__.
|
# It maintains state as we iterate.
|
||||||
our_iterator.__next__() #=> "two"
|
next(our_iterator) #=> "two"
|
||||||
our_iterator.__next__() #=> "three"
|
next(our_iterator) #=> "three"
|
||||||
|
|
||||||
# After the iterator has returned all of its data, it gives you a StopIterator Exception
|
# After the iterator has returned all of its data, it gives you a StopIterator Exception
|
||||||
our_iterator.__next__() # Raises StopIteration
|
next(our_iterator) # Raises StopIteration
|
||||||
|
|
||||||
# You can grab all the elements of an iterator by calling list() on it.
|
# You can grab all the elements of an iterator by calling list() on it.
|
||||||
list(filled_dict.keys()) #=> Returns ["one", "two", "three"]
|
list(filled_dict.keys()) #=> Returns ["one", "two", "three"]
|
||||||
@ -642,18 +642,18 @@ print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
|
|||||||
|
|
||||||
### Free Online
|
### Free Online
|
||||||
|
|
||||||
|
* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
|
||||||
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
|
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
|
||||||
* [Dive Into Python](http://www.diveintopython.net/)
|
* [Dive Into Python](http://www.diveintopython.net/)
|
||||||
* [Ideas for Python Projects](http://pythonpracticeprojects.com)
|
* [Ideas for Python Projects](http://pythonpracticeprojects.com)
|
||||||
|
|
||||||
* [The Official Docs](http://docs.python.org/3/)
|
* [The Official Docs](http://docs.python.org/3/)
|
||||||
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
||||||
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
|
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
|
||||||
* [Python Course](http://www.python-course.eu/index.php)
|
* [Python Course](http://www.python-course.eu/index.php)
|
||||||
|
* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
|
||||||
|
|
||||||
### Dead Tree
|
### Dead Tree
|
||||||
|
|
||||||
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
|
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
|
||||||
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
|
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
|
||||||
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
|
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
|
||||||
|
|
||||||
|
@ -212,7 +212,9 @@ The source can be found on [github](https://github.com/red/red).
|
|||||||
|
|
||||||
The Red/System language specification can be found [here](http://static.red-lang.org/red-system-specs-light.html).
|
The Red/System language specification can be found [here](http://static.red-lang.org/red-system-specs-light.html).
|
||||||
|
|
||||||
To learn more about Rebol and Red join the [chat on StackOverflow](http://chat.stackoverflow.com/rooms/291/rebol-and-red). You will need 20 points to chat but if you ask or answer questions about Red or Rebol we will help you get those points. And if that is not working for you drop a mail to us on the [Red mailing list](mailto: red-langNO_SPAM@googlegroups.com) (remove NO_SPAM).
|
To learn more about Rebol and Red join the [chat on Gitter](https://gitter.im/red/red). And if that is not working for you drop a mail to us on the [Red mailing list](mailto: red-langNO_SPAM@googlegroups.com) (remove NO_SPAM).
|
||||||
|
|
||||||
|
Browse or ask questions on [Stack Overflow](stackoverflow.com/questions/tagged/red).
|
||||||
|
|
||||||
Maybe you want to try Red right away? That is possible on the [try Rebol and Red site](http://tryrebol.esperconsultancy.nl).
|
Maybe you want to try Red right away? That is possible on the [try Rebol and Red site](http://tryrebol.esperconsultancy.nl).
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ lang: ru-ru
|
|||||||
Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень
|
Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень
|
||||||
маленький Тьюринг-полный язык программирования лишь с 8 командами.
|
маленький Тьюринг-полный язык программирования лишь с 8 командами.
|
||||||
|
|
||||||
|
Вы можете испытать brainfuck в вашем браузере с помощью [brainfuck-визуализатора](http://fatiherikli.github.io/brainfuck-visualizer/).
|
||||||
|
|
||||||
```
|
```
|
||||||
Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек.
|
Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек.
|
||||||
|
|
||||||
|
@ -1,106 +1,171 @@
|
|||||||
---
|
---
|
||||||
language: Objective-C
|
language: Objective-C
|
||||||
filename: LearnObjectiveC.m
|
filename: LearnObjectiveC-ru.m
|
||||||
contributors:
|
contributors:
|
||||||
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
|
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
|
||||||
- ["Yannick Loriot", "https://github.com/YannickL"]
|
- ["Yannick Loriot", "https://github.com/YannickL"]
|
||||||
|
- ["Levi Bostian", "https://github.com/levibostian"]
|
||||||
translators:
|
translators:
|
||||||
- ["Evlogy Sutormin", "http://evlogii.com"]
|
- ["Evlogy Sutormin", "http://evlogii.com"]
|
||||||
|
- ["Dmitry Bessonov", "https://github.com/TheDmitry"]
|
||||||
lang: ru-ru
|
lang: ru-ru
|
||||||
---
|
---
|
||||||
|
|
||||||
Objective-C — компилируемый объектно-ориентированный язык программирования, используемый корпорацией Apple,
|
Objective-C — основной язык программирования, используемый корпорацией Apple
|
||||||
построенный на основе языка Си и парадигм Smalltalk.
|
для операционных систем OS X и iOS и их соответствующих фреймворках Cocoa и
|
||||||
В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения.
|
Cocoa Touch.
|
||||||
|
Он является объектно-ориентированным языком программирования общего назначения,
|
||||||
|
который добавляет обмен сообщениями в Smalltalk-стиле к языку программирования C.
|
||||||
|
|
||||||
```objective_c
|
```objective_c
|
||||||
// Однострочный комментарий
|
// Однострочные комментарии начинаются с //
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Многострочный
|
Так выглядят многострочные комментарии
|
||||||
комментарий
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Импорт файлов фреймворка Foundation с помощью #import
|
// Импорт заголовочных файлов фреймворка Foundation с помощью #import
|
||||||
|
// Используйте <>, чтобы импортировать глобальные файлы (обычно фреймворки)
|
||||||
|
// Используйте "", чтобы импортировать локальные файлы (из проекта)
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "MyClass.h"
|
#import "MyClass.h"
|
||||||
|
|
||||||
// Точка входа в программу это функция main,
|
// Если вы включили модули для iOS >= 7.0 или OS X >= 10.9 проектов в
|
||||||
// которая возвращает целый тип integer
|
// Xcode 5, вы можете импортировать фреймворки подобным образом:
|
||||||
|
@import Foundation;
|
||||||
|
|
||||||
|
// Точка входа в программу - это функция main,
|
||||||
|
// которая возвращает целый тип
|
||||||
int main (int argc, const char * argv[])
|
int main (int argc, const char * argv[])
|
||||||
{
|
{
|
||||||
// Создание autorelease pool для управления памятью
|
// Создание autorelease pool для управления памятью в программе
|
||||||
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
// В место этого воспользуйтесь @autoreleasepool, если вы используете
|
||||||
|
// автоматический подсчет ссылок (ARC)
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
// Используйте NSLog для печати в консоль
|
// Используйте NSLog для печати в консоль
|
||||||
NSLog(@"Hello World!"); // Напечатает строку "Hello World!"
|
NSLog(@"Привет Мир!"); // Напечатает строку "Привет Мир!"
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Типы и переменные
|
// Типы и переменные
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
// Простое объявление
|
// Объявление простых типов
|
||||||
int myPrimitive1 = 1;
|
int myPrimitive1 = 1;
|
||||||
long myPrimitive2 = 234554664565;
|
long myPrimitive2 = 234554664565;
|
||||||
|
|
||||||
|
// Объявление объектов
|
||||||
// Помещайте * в начало названия объекта для строго типизированного объявления
|
// Помещайте * в начало названия объекта для строго типизированного объявления
|
||||||
MyClass *myObject1 = nil; // Строгая типизация
|
MyClass *myObject1 = nil; // Строгая типизация
|
||||||
id myObject2 = nil; // Слабая типизация
|
id myObject2 = nil; // Слабая типизация
|
||||||
|
|
||||||
NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
|
|
||||||
// %@ – это объект
|
// %@ – это объект
|
||||||
// 'description' это общий для всех объектов метод вывода данных
|
// 'description' - это общий для всех объектов метод вывода данных
|
||||||
|
NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
|
||||||
|
|
||||||
// Строка
|
// Строка
|
||||||
NSString *worldString = @"World";
|
NSString *worldString = @"Мир";
|
||||||
NSLog(@"Hello %@!", worldString); // напечатает "Hello World!"
|
NSLog(@"Привет %@!", worldString); // напечатает "Привет Мир!"
|
||||||
|
// NSMutableString - это изменяемая версия NSString-объекта
|
||||||
|
NSMutableString *mutableString = [NSMutableString stringWithString:@"Привет"];
|
||||||
|
[mutableString appendString:@" Мир!"];
|
||||||
|
NSLog(@"%@", mutableString); // напечатает => "Привет Мир!"
|
||||||
|
|
||||||
// Символьные литералы
|
// Символьные литералы
|
||||||
NSNumber *theLetterZNumber = @'Z';
|
NSNumber *theLetterZNumber = @'Z';
|
||||||
char theLetterZ = [theLetterZNumber charValue];
|
char theLetterZ = [theLetterZNumber charValue]; // или 'Z'
|
||||||
NSLog(@"%c", theLetterZ);
|
NSLog(@"%c", theLetterZ);
|
||||||
|
|
||||||
// Целочисленный литералы
|
// Целочисленные литералы
|
||||||
NSNumber *fortyTwoNumber = @42;
|
NSNumber *fortyTwoNumber = @42;
|
||||||
int fortyTwo = [fortyTwoNumber intValue];
|
int fortyTwo = [fortyTwoNumber intValue]; // или '42'
|
||||||
NSLog(@"%i", fortyTwo);
|
NSLog(@"%i", fortyTwo);
|
||||||
|
|
||||||
// Беззнаковый целочисленный литерал
|
// Беззнаковый целочисленный литерал
|
||||||
NSNumber *fortyTwoUnsignedNumber = @42U;
|
NSNumber *fortyTwoUnsignedNumber = @42U;
|
||||||
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
|
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // или 42
|
||||||
NSLog(@"%u", fortyTwoUnsigned);
|
NSLog(@"%u", fortyTwoUnsigned);
|
||||||
|
|
||||||
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
|
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
|
||||||
short fortyTwoShort = [fortyTwoShortNumber shortValue];
|
short fortyTwoShort = [fortyTwoShortNumber shortValue]; // или 42
|
||||||
NSLog(@"%hi", fortyTwoShort);
|
NSLog(@"%hi", fortyTwoShort);
|
||||||
|
|
||||||
|
NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41];
|
||||||
|
unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // или 41
|
||||||
|
NSLog(@"%u", fortyOneUnsigned);
|
||||||
|
|
||||||
NSNumber *fortyTwoLongNumber = @42L;
|
NSNumber *fortyTwoLongNumber = @42L;
|
||||||
long fortyTwoLong = [fortyTwoLongNumber longValue];
|
long fortyTwoLong = [fortyTwoLongNumber longValue]; // или 42
|
||||||
NSLog(@"%li", fortyTwoLong);
|
NSLog(@"%li", fortyTwoLong);
|
||||||
|
|
||||||
|
NSNumber *fiftyThreeLongNumber = @53L;
|
||||||
|
unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // или 53
|
||||||
|
NSLog(@"%lu", fiftyThreeUnsigned);
|
||||||
|
|
||||||
// Вещественный литерал
|
// Вещественный литерал
|
||||||
NSNumber *piFloatNumber = @3.141592654F;
|
NSNumber *piFloatNumber = @3.141592654F;
|
||||||
float piFloat = [piFloatNumber floatValue];
|
float piFloat = [piFloatNumber floatValue]; // или 3.141592654f
|
||||||
NSLog(@"%f", piFloat);
|
NSLog(@"%f", piFloat); // напечатает 3.141592654
|
||||||
|
NSLog(@"%5.2f", piFloat); // напечатает " 3.14"
|
||||||
|
|
||||||
NSNumber *piDoubleNumber = @3.1415926535;
|
NSNumber *piDoubleNumber = @3.1415926535;
|
||||||
double piDouble = [piDoubleNumber doubleValue];
|
double piDouble = [piDoubleNumber doubleValue]; // или 3.1415926535
|
||||||
NSLog(@"%f", piDouble);
|
NSLog(@"%f", piDouble);
|
||||||
|
NSLog(@"%4.2f", piDouble); // напечатает "3.14"
|
||||||
|
|
||||||
|
// NSDecimalNumber - это класс с фиксированной точкой, который является
|
||||||
|
// более точным, чем float или double
|
||||||
|
NSDecimalNumber *oneDecNum = [NSDecimalNumber decimalNumberWithString:@"10.99"];
|
||||||
|
NSDecimalNumber *twoDecNum = [NSDecimalNumber decimalNumberWithString:@"5.002"];
|
||||||
|
// NSDecimalNumber не способен использовать стандартные +, -, *, / операторы,
|
||||||
|
// поэтому он предоставляет свои собственные:
|
||||||
|
[oneDecNum decimalNumberByAdding:twoDecNum];
|
||||||
|
[oneDecNum decimalNumberBySubtracting:twoDecNum];
|
||||||
|
[oneDecNum decimalNumberByMultiplyingBy:twoDecNum];
|
||||||
|
[oneDecNum decimalNumberByDividingBy:twoDecNum];
|
||||||
|
NSLog(@"%@", oneDecNum); // напечатает "10.99", т.к. NSDecimalNumber - изменяемый
|
||||||
|
|
||||||
// BOOL (булевый) литерал
|
// BOOL (булевый) литерал
|
||||||
NSNumber *yesNumber = @YES;
|
NSNumber *yesNumber = @YES;
|
||||||
NSNumber *noNumber = @NO;
|
NSNumber *noNumber = @NO;
|
||||||
|
// или
|
||||||
|
BOOL yesBool = YES;
|
||||||
|
BOOL noBool = NO;
|
||||||
|
NSLog(@"%i", yesBool); // напечатает 1
|
||||||
|
|
||||||
// Массив
|
// Массив
|
||||||
|
// Может содержать различные типы данных, но должен быть объектом Objective-C
|
||||||
NSArray *anArray = @[@1, @2, @3, @4];
|
NSArray *anArray = @[@1, @2, @3, @4];
|
||||||
NSNumber *thirdNumber = anArray[2];
|
NSNumber *thirdNumber = anArray[2];
|
||||||
NSLog(@"Third number = %@", thirdNumber); // Print "Third number = 3"
|
NSLog(@"Третье число = %@", thirdNumber); // Напечатает "Третье число = 3"
|
||||||
|
// NSMutableArray - это изменяемая версия NSArray, допускающая вам изменять
|
||||||
|
// элементы в массиве и расширять или сокращать массив.
|
||||||
|
// Удобный, но не эффективный как NSArray.
|
||||||
|
NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2];
|
||||||
|
[mutableArray addObject:@"Привет"];
|
||||||
|
[mutableArray addObject:@"Мир"];
|
||||||
|
[mutableArray removeObjectAtIndex:0];
|
||||||
|
NSLog(@"%@", [mutableArray objectAtIndex:0]); // напечатает "Мир"
|
||||||
|
|
||||||
// Словарь
|
// Словарь
|
||||||
NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
|
NSDictionary *aDictionary = @{ @"ключ1" : @"значение1", @"ключ2" : @"значение2" };
|
||||||
NSObject *valueObject = aDictionary[@"A Key"];
|
NSObject *valueObject = aDictionary[@"Ключ"];
|
||||||
NSLog(@"Object = %@", valueObject); // Напечатает "Object = (null)"
|
NSLog(@"Объект = %@", valueObject); // Напечатает "Объект = (null)"
|
||||||
|
// NSMutableDictionary тоже доступен, как изменяемый словарь
|
||||||
|
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2];
|
||||||
|
[mutableDictionary setObject:@"значение1" forKey:@"ключ1"];
|
||||||
|
[mutableDictionary setObject:@"значение2" forKey:@"ключ2"];
|
||||||
|
[mutableDictionary removeObjectForKey:@"ключ1"];
|
||||||
|
|
||||||
|
// Множество
|
||||||
|
NSSet *set = [NSSet setWithObjects:@"Привет", @"Привет", @"Мир", nil];
|
||||||
|
NSLog(@"%@", set); // напечатает {(Hello, World)} (порядок может отличаться)
|
||||||
|
// NSMutableSet тоже доступен, как изменяемое множество
|
||||||
|
NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2];
|
||||||
|
[mutableSet addObject:@"Привет"];
|
||||||
|
[mutableSet addObject:@"Привет"];
|
||||||
|
NSLog(@"%@", mutableSet); // напечатает => {(Привет)}
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Операторы
|
// Операторы
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
@ -124,13 +189,13 @@ int main (int argc, const char * argv[])
|
|||||||
// Условный оператор
|
// Условный оператор
|
||||||
if (NO)
|
if (NO)
|
||||||
{
|
{
|
||||||
NSLog(@"I am never run");
|
NSLog(@"Я никогда не выполнюсь");
|
||||||
} else if (0)
|
} else if (0)
|
||||||
{
|
{
|
||||||
NSLog(@"I am also never run");
|
NSLog(@"Я тоже никогда не выполнюсь");
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
NSLog(@"I print");
|
NSLog(@"Я напечатаюсь");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ветвление с множественным выбором
|
// Ветвление с множественным выбором
|
||||||
@ -138,15 +203,15 @@ int main (int argc, const char * argv[])
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
NSLog(@"I am never run");
|
NSLog(@"Я никогда не выполнюсь");
|
||||||
} break;
|
} break;
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
NSLog(@"I am also never run");
|
NSLog(@"Я тоже никогда не выполнюсь");
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
NSLog(@"I print");
|
NSLog(@"Я напечатаюсь");
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +235,7 @@ int main (int argc, const char * argv[])
|
|||||||
// "2,"
|
// "2,"
|
||||||
// "3,"
|
// "3,"
|
||||||
|
|
||||||
// // Цикл просмотра
|
// Цикл просмотра
|
||||||
NSArray *values = @[@0, @1, @2, @3];
|
NSArray *values = @[@0, @1, @2, @3];
|
||||||
for (NSNumber *value in values)
|
for (NSNumber *value in values)
|
||||||
{
|
{
|
||||||
@ -180,20 +245,32 @@ int main (int argc, const char * argv[])
|
|||||||
// "2,"
|
// "2,"
|
||||||
// "3,"
|
// "3,"
|
||||||
|
|
||||||
|
// Цикл for для объектов. Может использоваться с любым объектом Objective-C
|
||||||
|
for (id item in values) {
|
||||||
|
NSLog(@"%@,", item);
|
||||||
|
} // напечатает => "0,"
|
||||||
|
// "1,"
|
||||||
|
// "2,"
|
||||||
|
// "3,"
|
||||||
|
|
||||||
// Обработка исключений
|
// Обработка исключений
|
||||||
@try
|
@try
|
||||||
{
|
{
|
||||||
// Ваше исключение здесь
|
// Ваше исключение здесь
|
||||||
@throw [NSException exceptionWithName:@"FileNotFoundException"
|
@throw [NSException exceptionWithName:@"FileNotFoundException"
|
||||||
reason:@"File Not Found on System" userInfo:nil];
|
reason:@"Файл не найден в системе" userInfo:nil];
|
||||||
} @catch (NSException * e)
|
} @catch (NSException * e)
|
||||||
{
|
{
|
||||||
NSLog(@"Exception: %@", e);
|
NSLog(@"Исключение: %@", e);
|
||||||
} @finally
|
} @finally
|
||||||
{
|
{
|
||||||
NSLog(@"Finally");
|
NSLog(@"В конце отводится время для очистки.");
|
||||||
} // => напечатает "Exception: File Not Found on System"
|
} // => напечатает "Исключение: Файл не найден в системе"
|
||||||
// "Finally"
|
// "В конце отводится время для очистки."
|
||||||
|
|
||||||
|
// NSError - это полезные объекты для аргументов функции, чтобы заполнить их
|
||||||
|
// пользовательскими ошибками.
|
||||||
|
NSError *error = [NSError errorWithDomain:@"Неправильный эл. адрес." code:4 userInfo:nil];
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Объекты
|
// Объекты
|
||||||
@ -203,13 +280,16 @@ int main (int argc, const char * argv[])
|
|||||||
// Объект не является полнофункциональным пока обе части не выполнятся.
|
// Объект не является полнофункциональным пока обе части не выполнятся.
|
||||||
MyClass *myObject = [[MyClass alloc] init];
|
MyClass *myObject = [[MyClass alloc] init];
|
||||||
|
|
||||||
// В Objective-C можель ООП базируется на передаче сообщений.
|
// В Objective-C модель ООП базируется на передаче сообщений.
|
||||||
// В Objective-C Вы не просто вызваете метод; вы посылаете сообщение.
|
// В Objective-C Вы не просто вызваете метод; вы посылаете сообщение.
|
||||||
[myObject instanceMethodWithParameter:@"Steve Jobs"];
|
[myObject instanceMethodWithParameter:@"Стив Джобс"];
|
||||||
|
|
||||||
// Очищайте память, перед завершением работы программы.
|
// Очищайте память, перед завершением работы программы.
|
||||||
[pool drain];
|
[pool drain];
|
||||||
|
|
||||||
|
// Конец @autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
// Конец программы.
|
// Конец программы.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -222,63 +302,144 @@ int main (int argc, const char * argv[])
|
|||||||
// Синтаксис объявления:
|
// Синтаксис объявления:
|
||||||
// @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы>
|
// @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы>
|
||||||
// {
|
// {
|
||||||
// Объявление переменных;
|
// тип имя; <= Объявление переменных;
|
||||||
// }
|
// }
|
||||||
|
// @property тип имя; <= объявление свойств
|
||||||
// -/+ (тип) Объявление метода(ов).
|
// -/+ (тип) Объявление метода(ов).
|
||||||
// @end
|
// @end
|
||||||
|
@interface MyClass : NSObject <MyProtocol> // NSObject - это базовый класс в Objective-C.
|
||||||
|
|
||||||
@interface MyClass : NSObject <MyProtocol>
|
|
||||||
{
|
{
|
||||||
int count;
|
// Объявления экземпляров переменных (может существовать в файлах интерфейса или реализвации)
|
||||||
id data;
|
int count; // По умолчанию защищенный доступ.
|
||||||
|
@private id data; // Приватный доступ (Намного удобнее объявлять в файле реализации)
|
||||||
NSString *name;
|
NSString *name;
|
||||||
}
|
}
|
||||||
// При объявлении свойств сразу генерируются геттер и сеттер
|
// Удобное обозначение для переменных с открытым (public) доступом
|
||||||
@property int count;
|
// автоматически генерируется сеттер-метод
|
||||||
@property (copy) NSString *name; // Скопировать объект в ходе присвоения.
|
// По умолчанию название сеттер-метода начинается с 'set' с последующим именем
|
||||||
@property (readonly) id data; // Генерация только геттера
|
// переменной из @property
|
||||||
|
@property int propInt; // Имя сеттер-метода = 'setPropInt'
|
||||||
|
@property (copy) id copyId; // (copy) => Скопировать объект в ходе присвоения.
|
||||||
|
// (readonly) => Не позволяет установить значение вне @interface
|
||||||
|
@property (readonly) NSString *roString; // Используйте @synthesize
|
||||||
|
// в @implementation, чтобы создать аксессор
|
||||||
|
// Вы можете настроить геттер и сеттер имена вместо используемого 'set'-имени по умолчанию:
|
||||||
|
@property (getter=lengthGet, setter=lengthSet:) int length;
|
||||||
|
|
||||||
// Методы
|
// Методы
|
||||||
+/- (return type)methodSignature:(Parameter Type *)parameterName;
|
+/- (возвращаемый тип)сигнатураМетода:(Параметр типа *)имяПараметра;
|
||||||
|
|
||||||
// + для методов класса
|
// + для методов класса
|
||||||
+ (NSString *)classMethod;
|
+ (NSString *)classMethod;
|
||||||
|
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight;
|
||||||
|
|
||||||
// - для метода объекта
|
// - для методов объекта
|
||||||
- (NSString *)instanceMethodWithParameter:(NSString *)string;
|
- (NSString *)instanceMethodWithParameter:(NSString *)string;
|
||||||
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
|
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
|
||||||
|
|
||||||
@end
|
// Методы-конструктор с аргументом:
|
||||||
|
- (id)initWithDistance:(int)defaultDistance;
|
||||||
|
// В Objective-C имена методов очень описательные. Всегда имена методов соответствуют своим аргументам
|
||||||
|
|
||||||
|
@end // Устанавливает конец интерфейса (interface)
|
||||||
|
|
||||||
|
|
||||||
|
// Чтобы обратиться к открытым (public) переменным из файла реализации, @property генерирует сеттер-метод
|
||||||
|
// автоматически. Название метода - это 'set' с последующим именем переменной из @property:
|
||||||
|
MyClass *myClass = [[MyClass alloc] init]; // создает экземпляр объекта класса MyClass
|
||||||
|
[myClass setCount:10];
|
||||||
|
NSLog(@"%d", [myClass count]); // напечатает => 10
|
||||||
|
// Или используйте свой геттер и сеттер методы, которые определены в @interface:
|
||||||
|
[myClass lengthSet:32];
|
||||||
|
NSLog(@"%i", [myClass lengthGet]); // напечатает => 32
|
||||||
|
// Для удобства вы можете использовать точечную нотацию,
|
||||||
|
// чтобы установить и получить доступ к переменным объекта:
|
||||||
|
myClass.count = 45;
|
||||||
|
NSLog(@"%i", myClass.count); // напечатает => 45
|
||||||
|
|
||||||
|
// Вызов методов класса:
|
||||||
|
NSString *classMethodString = [MyClass classMethod];
|
||||||
|
MyClass *classFromName = [MyClass myClassFromName:@"Привет"];
|
||||||
|
|
||||||
|
// Вызов методов экземпляра:
|
||||||
|
MyClass *myClass = [[MyClass alloc] init]; // Создает экземпляр объекта MyClass
|
||||||
|
NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Привет"];
|
||||||
|
|
||||||
|
// Селекторы
|
||||||
|
// Это способ динамически представить методы. Используйте для вызова методов класса, передайте методы
|
||||||
|
// через функции, чтобы сказать другим классам, что они должны вызвать их и сохранить методы
|
||||||
|
// как переменные
|
||||||
|
// SEL - это тип данных. @selector() вернет селектор из предоставленного имени метода
|
||||||
|
// methodAParameterAsString:andAParameterAsNumber: - это название метода в MyClass
|
||||||
|
SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:);
|
||||||
|
if ([myClass respondsToSelector:selectorVar]) { // Проверяет содержит ли класс метод
|
||||||
|
// Необходимо установить все аргументы метода в один объект, что отправить его в performSelector-функцию
|
||||||
|
NSArray *arguments = [NSArray arrayWithObjects:@"Привет", @4, nil];
|
||||||
|
[myClass performSelector:selectorVar withObject:arguments]; // Вызывает метод
|
||||||
|
} else {
|
||||||
|
// NSStringFromSelector() вернет NSString название метода полученного селектором
|
||||||
|
NSLog(@"MyClass не содержит метод: %@", NSStringFromSelector(selectedVar));
|
||||||
|
}
|
||||||
|
|
||||||
// Имплементируйте методы в файле МойКласс.m:
|
// Имплементируйте методы в файле МойКласс.m:
|
||||||
|
@implementation MyClass {
|
||||||
|
long distance; // Переменная экземпляра с закрытым (private) доступом
|
||||||
|
NSNumber height;
|
||||||
|
}
|
||||||
|
|
||||||
@implementation MyClass
|
// To access a public variable from the interface file, use '_' followed by variable name:
|
||||||
|
_count = 5; // References "int count" from MyClass interface
|
||||||
|
// Access variables defined in implementation file:
|
||||||
|
distance = 18; // References "long distance" from MyClass implementation
|
||||||
|
// To use @property variable in implementation, use @synthesize to create accessor variable:
|
||||||
|
@synthesize roString = _roString; // _roString available now in @implementation
|
||||||
|
|
||||||
|
// Called before calling any class methods or instantiating any objects
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
if (self == [MyClass class]) {
|
||||||
|
distance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Вызывается при высвобождении памяти под объектом
|
// Вызывается при высвобождении памяти под объектом
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
|
[height release]; // Если не используется ARC, убедитесь в освобождении переменных объекта класса
|
||||||
|
[super dealloc]; // and call parent class dealloc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Конструкторы – это способ осздания объектов класса.
|
// Конструкторы – это способ создания объектов класса.
|
||||||
// Это обычный конструктор вызываемый при создании объекта клсааа.
|
// Это конструктор по умолчанию, который вызывается, когда объект инициализируется.
|
||||||
- (id)init
|
- (id)init
|
||||||
{
|
{
|
||||||
if ((self = [super init]))
|
if ((self = [super init])) // 'super' используется для того, чтобы обратиться к методам родительского класса
|
||||||
{
|
{
|
||||||
self.count = 1;
|
self.count = 1; // 'self' используется для вызова самого себя
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
// Можно создать конструкторы, которые содержат аргументы:
|
||||||
|
- (id)initWithDistance:(int)defaultDistance
|
||||||
|
{
|
||||||
|
distance = defaultDistance;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSString *)classMethod
|
+ (NSString *)classMethod
|
||||||
{
|
{
|
||||||
return [[self alloc] init];
|
return [[self alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
|
||||||
|
{
|
||||||
|
height = defaultHeight;
|
||||||
|
return [[self alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *)instanceMethodWithParameter:(NSString *)string
|
- (NSString *)instanceMethodWithParameter:(NSString *)string
|
||||||
{
|
{
|
||||||
return @"New string";
|
return @"Новая строка";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
|
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
|
||||||
@ -286,23 +447,364 @@ int main (int argc, const char * argv[])
|
|||||||
return @42;
|
return @42;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Objective-C не содержит объявление приватных методов, но вы можете имитировать их.
|
||||||
|
// Чтобы сымитировать приватный метод, создайте метод в @implementation, но не в @interface.
|
||||||
|
- (NSNumber *)secretPrivateMethod {
|
||||||
|
return @72;
|
||||||
|
}
|
||||||
|
[self secretPrivateMethod]; // Вызывает приватный метод
|
||||||
|
|
||||||
// Методы объявленные в МyProtocol (см. далее)
|
// Методы объявленные в МyProtocol (см. далее)
|
||||||
- (void)myProtocolMethod
|
- (void)myProtocolMethod
|
||||||
{
|
{
|
||||||
// имплементация
|
// операторы
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // Устанавливает конец реализации (implementation)
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Категории
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Категория - это группа методов предназначенные для того, чтобы расширить класс. Они позволяют вам добавить новые методы
|
||||||
|
// к существующему классу для организационных целей. Это не стоит путать с подклассами.
|
||||||
|
// Подклассы предназначены для ИЗМЕНЕНИЯ функциональности объекта пока как категории ДОБАВЛЯЮТ
|
||||||
|
// функциональность в объект.
|
||||||
|
// Категории позволяют вам:
|
||||||
|
// -- Добавлять методы в существующий класс для организационных целей.
|
||||||
|
// -- Допускает вам расширять объекты Objective-C классов (напр.: NSString) добавить ваши собственные методы.
|
||||||
|
// -- Добавляет возможность создать защищенные и закрытые методы классов.
|
||||||
|
// ПРИМЕЧАНИЕ: Не переопределяйте методы базового класса в категории даже если у вас есть возможность это сделать
|
||||||
|
// to. Переопределение методов может привести к ошибкам компиляции позднее между различными категориями и это
|
||||||
|
// нарушает цель категорий, чтобы добавлять только функциональность. Вместо этого подклассы переопределяют методы.
|
||||||
|
|
||||||
|
// Здесь простой базовый класс Car.
|
||||||
|
@interface Car : NSObject
|
||||||
|
|
||||||
|
@property NSString *make;
|
||||||
|
@property NSString *color;
|
||||||
|
|
||||||
|
- (void)turnOn;
|
||||||
|
- (void)accelerate;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// И реализация базового класса Car:
|
||||||
|
#import "Car.h"
|
||||||
|
|
||||||
|
@implementation Car
|
||||||
|
|
||||||
|
@synthesize make = _make;
|
||||||
|
@synthesize color = _color;
|
||||||
|
|
||||||
|
- (void)turnOn {
|
||||||
|
NSLog(@"Машина заведена.");
|
||||||
|
}
|
||||||
|
- (void)accelerate {
|
||||||
|
NSLog(@"Ускорение.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/*
|
// Теперь, если мы хотели создать грузовой объект, мы должны вместо создания подкласса класса Car, как это будет
|
||||||
* Протокол объявляет методы которые должны быть имплементированы
|
// изменять функциональность Car чтобы вести себя подобно грузовику. Но давайте посмотрим, если мы хотим только добавить
|
||||||
* Протокол не является классом. Он просто определяет интерфейс,
|
// функциональность в существующий Car. Хороший пример должен быть чистить автомобиль. Итак мы создадим
|
||||||
* который должен быть имплементирован.
|
// категорию для добавления его очистительных методов:
|
||||||
*/
|
// @interface ИмяФайла: Car+Clean.h (ИмяБазовогоКласса+ИмяКатегории.h)
|
||||||
|
#import "Car.h" // Убедитесь в том, что базовый класс импортирован для расширения.
|
||||||
|
|
||||||
|
@interface Car (Clean) // Имя категории внутри (), следующие после имени базового класса.
|
||||||
|
|
||||||
|
- (void)washWindows; // Названия новых методов, которые мы добавляем в наш объект Car.
|
||||||
|
- (void)wax;
|
||||||
|
|
||||||
@protocol MyProtocol
|
|
||||||
- (void)myProtocolMethod;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
// @implementation имя файла: Car+Clean.m (ИмяБазовогоКласса+ИмяКатегории.m)
|
||||||
|
#import "Car+Clean.h" // Импортируйте Очистку файл @interface категории.
|
||||||
|
|
||||||
|
@implementation Car (Clean)
|
||||||
|
|
||||||
|
- (void)washWindows {
|
||||||
|
NSLog(@"Окна промыли.");
|
||||||
|
}
|
||||||
|
- (void)wax {
|
||||||
|
NSLog(@"Воском натерли.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// Любой экземпляр объекта Car имеет возможность воспользоваться категорией. Все, что нужно сделать, это импортировать ее:
|
||||||
|
#import "Car+Clean.h" // Импортировать как множество различных категорий, как вы хотите использовать.
|
||||||
|
#import "Car.h" // Кроме того, необходимо импортировать базовый класс для использования его оригинальные функциональные возможности.
|
||||||
|
|
||||||
|
int main (int argc, const char * argv[]) {
|
||||||
|
@autoreleasepool {
|
||||||
|
Car *mustang = [[Car alloc] init];
|
||||||
|
mustang.color = @"Красный";
|
||||||
|
mustang.make = @"Форд";
|
||||||
|
|
||||||
|
[mustang turnOn]; // Используйте методы из базового класса Car.
|
||||||
|
[mustang washWindows]; // Используйте методы категории Clean из класса Car.
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Objective-C не поддерживает объявление защищенных методов, но вы можете имитировать их.
|
||||||
|
// Создайте категорию, содержащую все защищенные методы, затем импортируйте ее только в
|
||||||
|
// @implementation-файле класса, относящегося к классу Car:
|
||||||
|
@interface Car (Protected) // Наименование категории с помощью 'Protected'
|
||||||
|
// дает знать, что методы защищенные.
|
||||||
|
|
||||||
|
- (void)lockCar; // Здесь перечисляются методы, которые должны быть созданы
|
||||||
|
// только с помощью объектов класса Car.
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Чтобы воспользоваться защищенными методами, импортируйте категорию, затем реализуйте методы:
|
||||||
|
#import "Car+Protected.h" // Запомните, делайте импорт только в файле с @implementation.
|
||||||
|
|
||||||
|
@implementation Car
|
||||||
|
|
||||||
|
- (void)lockCar {
|
||||||
|
NSLog(@"Машина закрыта."); // Экземпляры класса Car не могут использовать
|
||||||
|
// метод lockCar, потому что он объявлен не в @interface.
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Расширения
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Расширения позволяют вам переопределять атрибуты свойств и методов
|
||||||
|
// с открытым доступом в @interface.
|
||||||
|
// @interface имя файла: Shape.h
|
||||||
|
@interface Shape : NSObject // Расширение базового класса Shape переопределяет
|
||||||
|
// свои поля ниже.
|
||||||
|
|
||||||
|
@property (readonly) NSNumber *numOfSides;
|
||||||
|
|
||||||
|
- (int)getNumOfSides;
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Вы можете переопределить numOfSides-переменную или getNumOfSides-метод
|
||||||
|
// Внесение изменений с помощью расширения делается следующим образом:
|
||||||
|
// @implementation имя файла: Shape.m
|
||||||
|
#import "Shape.h"
|
||||||
|
// Расширения "живут" в том же файле, где и @implementation класса.
|
||||||
|
@interface Shape () // После имени базового класса скобки () объявляют расширение.
|
||||||
|
|
||||||
|
@property (copy) NSNumber *numOfSides; // Делает numOfSides-свойство
|
||||||
|
// копирующим (copy) вместо свойства только для чтения (readonly).
|
||||||
|
-(NSNumber)getNumOfSides; // Изменяет метод getNumOfSides так,
|
||||||
|
// чтобы он возвращал объект NSNumber вместо типа int.
|
||||||
|
-(void)privateMethod; // Вы также можете создать новый закрытый метод
|
||||||
|
// внутри расширения.
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Главный @implementation:
|
||||||
|
@implementation Shape
|
||||||
|
|
||||||
|
@synthesize numOfSides = _numOfSides;
|
||||||
|
|
||||||
|
-(NSNumber)getNumOfSides { // Все операторы внутри расширения
|
||||||
|
// должны быть в @implementation.
|
||||||
|
return _numOfSides;
|
||||||
|
}
|
||||||
|
-(void)privateMethod {
|
||||||
|
NSLog(@"Закрытый метод созданный с помощью расширения.");
|
||||||
|
NSLog(@"Экземпляр Shape не может вызвать этот метод.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Протоколы
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Протокол объявляет методы, которые могут быть реализованы с помощью
|
||||||
|
// любого класса. Протоколы сами по себе не являются классами. Они просто
|
||||||
|
// определяют интерфейс, который должен быть реализован другими объектами.
|
||||||
|
// @protocol имя файла: "CarUtilities.h"
|
||||||
|
@protocol CarUtilities <NSObject> // <NSObject> => Имя другого протокола,
|
||||||
|
// который включен в этот протокол.
|
||||||
|
@property BOOL engineOn; // Адаптирующий класс должен определить
|
||||||
|
// все @synthesize для @property и
|
||||||
|
- (void)turnOnEngine; // определить все методы.
|
||||||
|
@end
|
||||||
|
// Ниже пример класса, реализующий протокол.
|
||||||
|
#import "CarUtilities.h" // Импорт файла с @protocol.
|
||||||
|
|
||||||
|
@interface Car : NSObject <CarUtilities> // Внутри <> имя протокола
|
||||||
|
// Здесь вам не нужно указывать @property или имена методов для CarUtilities.
|
||||||
|
// Они нужны только для @implementation.
|
||||||
|
- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // Вы также можете
|
||||||
|
// указать тип протоколов.
|
||||||
|
@end
|
||||||
|
// В @implementation нужно реализовать все @property и методы для протокола.
|
||||||
|
@implementation Car : NSObject <CarUtilities>
|
||||||
|
|
||||||
|
@synthesize engineOn = _engineOn; // Создайте @synthesize-оператор
|
||||||
|
// для "@property engineOn".
|
||||||
|
|
||||||
|
- (void)turnOnEngine { // Реализуйте turnOnEngine как вам угодно. Протоколы
|
||||||
|
// не определят,
|
||||||
|
_engineOn = YES; // как вам реализовать метод, он только требует,
|
||||||
|
// чтобы вы реализовали его.
|
||||||
|
}
|
||||||
|
// Вы можете использовать протокол как данные, если вы знаете, что он реализует
|
||||||
|
// методы и переменные.
|
||||||
|
- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {
|
||||||
|
[objectOfSomeKind engineOn]; // У вас есть доступ к переменным объекта
|
||||||
|
[objectOfSomeKind turnOnEngine]; // и методам.
|
||||||
|
[objectOfSomeKind engineOn]; // Может или не может быть значение YES. Класс
|
||||||
|
// реализует как нужно.
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Экземпляры класса Car сейчас имеют доступ к протоколу.
|
||||||
|
Car *carInstance = [[Car alloc] init];
|
||||||
|
[carInstance setEngineOn:NO];
|
||||||
|
[carInstance turnOnEngine];
|
||||||
|
if ([carInstance engineOn]) {
|
||||||
|
NSLog(@"Двигатель запущен."); // напечатает => "Двигатель запущен."
|
||||||
|
}
|
||||||
|
// Убедитись в том, что объект типа 'id' реализует протокол перед вызовом методов протокола:
|
||||||
|
if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
|
||||||
|
NSLog(@"Не работает, т.к. класс MyClass не реализует протокол CarUtilities.");
|
||||||
|
} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) {
|
||||||
|
NSLog(@"Работает как класс Car, который реализует протокол CarUtilities.");
|
||||||
|
}
|
||||||
|
// Категории тоже могут реализовать протоколы:
|
||||||
|
// @interface Car (CarCategory) <CarUtilities>
|
||||||
|
// Вы можете реализовать много протоколов:
|
||||||
|
// @interface Car : NSObject <CarUtilities, CarCleaning>
|
||||||
|
// ЗАМЕЧАНИЕ: Если два или более протоколов полагаются друг на друга,
|
||||||
|
// убедитесь, что они ранее объявлены:
|
||||||
|
#import "Brother.h"
|
||||||
|
|
||||||
|
@protocol Brother; // Оператор раннего объявления. Без него компилятор
|
||||||
|
// выдаст ошибку.
|
||||||
|
|
||||||
|
@protocol Sister <NSObject>
|
||||||
|
|
||||||
|
- (void)beNiceToBrother:(id <Brother>)brother;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// Рассмотрите проблему, где протокол Sister полагается на протокол Brother,
|
||||||
|
// а Brother полагается на Sister.
|
||||||
|
#import "Sister.h"
|
||||||
|
|
||||||
|
@protocol Sister; // Эти строки предотвращают рекурсию, решая этим проблему.
|
||||||
|
|
||||||
|
@protocol Brother <NSObject>
|
||||||
|
|
||||||
|
- (void)beNiceToSister:(id <Sister>)sister;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Блоки
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Блоки - это операторы кода, наподобие функции, которую возможно использовать
|
||||||
|
// как данные.
|
||||||
|
// Ниже простой блок с целочисленным аргументом, и возвращает аргумент плюс 4.
|
||||||
|
int (^addUp)(int n); // Объявите переменную, чтобы сохранить блок.
|
||||||
|
void (^noParameterBlockVar)(void); // Пример объявления блока-переменной
|
||||||
|
// без аргументов.
|
||||||
|
// Блоки имею доступ к переменным в той же области видимости. Но переменные
|
||||||
|
// будут только для чтения, и значения переданных в блок станут значением
|
||||||
|
// переменной, когда блок создастся.
|
||||||
|
int outsideVar = 17; // Если мы редактируем outsideVar после объявления addUp,
|
||||||
|
// outsideVar остается равным 17.
|
||||||
|
__block long mutableVar = 3; // __block делают переменные перезаписываемыми
|
||||||
|
// в блоках, в отличие от outsideVar.
|
||||||
|
addUp = ^(int n) { // Удалите (int n) в блоке, чтобы не принимать
|
||||||
|
// какие-либо параметры.
|
||||||
|
NSLog(@"Вы можете иметь столько строк в блоке, сколько вы хотели.");
|
||||||
|
NSSet *blockSet; // Также вы можете объявить локальные переменные.
|
||||||
|
mutableVar = 32; // Присвоить новое значение к __block-переменной.
|
||||||
|
return n + outsideVar; // Необязательный оператор возврата.
|
||||||
|
}
|
||||||
|
int addUp = add(10 + 16); // Вызывает блок кода с аргументами.
|
||||||
|
// Блоки часто используются как аргументы функции, чтобы позже их вызвать, или
|
||||||
|
// как функции обратного вызова (callbacks).
|
||||||
|
@implementation BlockExample : NSObject
|
||||||
|
|
||||||
|
- (void)runBlock:(void (^)(NSString))block {
|
||||||
|
NSLog(@"В аргументе блок ничего не возвращает и принимает NSString-объект.");
|
||||||
|
block(@"Аргумент передан блоку на исполнение."); // Вызов блока.
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Управление памятью
|
||||||
|
///////////////////////////////////////
|
||||||
|
/*
|
||||||
|
Для каждого объекта, используемого в приложении, должна быть выделена память
|
||||||
|
для таких объектов. Когда приложение прекращает использование объекта, память
|
||||||
|
должна быть освобождена, чтобы гарантировать эффективность приложения.
|
||||||
|
Objective-C не использует сборщик мусора, а вместо этого применяет подсчет ссылок.
|
||||||
|
Пока существует по крайней мере одна ссылка на объект (также называется
|
||||||
|
"владение" объектом), то объект будет доступен к использованию (еще известно
|
||||||
|
как "право владения").
|
||||||
|
|
||||||
|
Когда экземпляр владеет объектом, его ссылка увеличивается на один. Когда
|
||||||
|
объекта освобождается, счетчик ссылки уменьшается на один. Когда счетчик ссылки
|
||||||
|
равен нулю, объект удаляется из памяти.
|
||||||
|
|
||||||
|
Над всеми объектами взаимодействуют, следуя паттерну:
|
||||||
|
(1) создание объекта, (2) использование объекта, (3) затем освобождение объекта из памяти.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MyClass *classVar = [MyClass alloc]; // 'alloc' устанавливает счетчик ссылки
|
||||||
|
// объекта classVar на 1 и возвращает указатель на объект.
|
||||||
|
[classVar release]; // Уменьшает счетчик ссылки объекта classVar
|
||||||
|
// 'retain' заявляет право собственности на существующий экземпляр объекта
|
||||||
|
// и увеличивает счетчик ссылки. Затем вернет указатель на объект.
|
||||||
|
MyClass *newVar = [classVar retain]; // Если classVar освободится, объект
|
||||||
|
// останется в памяти, потому что newVar - владелец
|
||||||
|
[classVar autorelease]; // Удалит право на владение объектом
|
||||||
|
// в конце @autoreleasepool блока. Вернет указатель на объект.
|
||||||
|
|
||||||
|
// @property может использовать 'retain' и 'assign' тоже для маленького
|
||||||
|
// удобного определения
|
||||||
|
@property (retain) MyClass *instance; // Освободит старое значение и сохранит
|
||||||
|
// одно новое (строгая ссылка)
|
||||||
|
@property (assign) NSSet *set; // Укажет на новое значение
|
||||||
|
// без сохранения/освобождения старого значения (слабая ссылка)
|
||||||
|
|
||||||
|
// Автоматический подсчет ссылок (ARC)
|
||||||
|
// Управление памятью может быть трудным, поэтому в Xcode 4.2 и iOS 4 введен
|
||||||
|
// автоматический подсчет ссылок (ARC).
|
||||||
|
// ARC - это особенность компилятора, который помещает "retain", "release"
|
||||||
|
// и "autorelease" автоматически за вас тогда, когда используется ARC,
|
||||||
|
// вам не нужно больше обращаться к "retain", "relase" или "autorelease"
|
||||||
|
MyClass *arcMyClass = [[MyClass alloc] init];
|
||||||
|
// ... код, использующий объект arcMyClass
|
||||||
|
// Без ARC, вам нужно было бы вызвать: [arcMyClass release] после того, как вы
|
||||||
|
// завершите работу с объектом arcMyClass. Но с ARC,
|
||||||
|
// теперь этого не нужно делать. Он будет помещать release-вызов за вас
|
||||||
|
|
||||||
|
// Что касается 'assign' и 'retain' @property атрибутов, в ARC вы должны
|
||||||
|
// использовать 'weak' и 'strong'
|
||||||
|
@property (weak) MyClass *weakVar; // 'weak' не принимает право на владение
|
||||||
|
// объектом. Если исходный счетчик ссылки экземпляра обнуляется,
|
||||||
|
// weakVar-свойство автоматически примет значение nil,
|
||||||
|
// во избежание падения приложения
|
||||||
|
@property (strong) MyClass *strongVar; // 'strong' принимает право на владение
|
||||||
|
// объектом. Гарантирует, что объект останится в памяти для использования
|
||||||
|
|
||||||
|
// Для обычных переменных (не объявленных с помощью @property), используйте
|
||||||
|
// следующий способ:
|
||||||
|
__strong NSString *strongString; // По умолчанию. Переменная сохраняется в памяти,
|
||||||
|
// пока она не покинет область видимости
|
||||||
|
__weak NSSet *weakSet; // Слабая ссылка на существующий объект. Когда существующий
|
||||||
|
// объект освобождается, weakSet принимает nil
|
||||||
|
__unsafe_unretained NSArray *unsafeArray; // Похож на __weak, но unsafeArray
|
||||||
|
// не принимает nil, когда существующий объект освобождается
|
||||||
|
|
||||||
```
|
```
|
||||||
## На почитать
|
## На почитать
|
||||||
|
|
||||||
|
@ -173,6 +173,8 @@ array[1..3] #=> [2, 3, 4]
|
|||||||
|
|
||||||
# Add to an array like this
|
# Add to an array like this
|
||||||
array << 6 #=> [1, 2, 3, 4, 5, 6]
|
array << 6 #=> [1, 2, 3, 4, 5, 6]
|
||||||
|
# Or like this
|
||||||
|
array.push(6) #=> [1, 2, 3, 4, 5, 6]
|
||||||
|
|
||||||
# Check if an item exists in an array
|
# Check if an item exists in an array
|
||||||
array.include?(1) #=> true
|
array.include?(1) #=> true
|
||||||
|
@ -5,7 +5,7 @@ contributors:
|
|||||||
filename: learnrust.rs
|
filename: learnrust.rs
|
||||||
---
|
---
|
||||||
|
|
||||||
Rust is an in-development programming language developed by Mozilla Research.
|
Rust is a programming language developed by Mozilla Research.
|
||||||
Rust combines low-level control over performance with high-level convenience and
|
Rust combines low-level control over performance with high-level convenience and
|
||||||
safety guarantees.
|
safety guarantees.
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ fn main() {
|
|||||||
// This is basically an immutable pointer to a string – it doesn’t
|
// This is basically an immutable pointer to a string – it doesn’t
|
||||||
// actually contain the contents of a string, just a pointer to
|
// actually contain the contents of a string, just a pointer to
|
||||||
// something that does (in this case, `s`)
|
// something that does (in this case, `s`)
|
||||||
let s_slice: &str = &*s;
|
let s_slice: &str = &s;
|
||||||
|
|
||||||
println!("{} {}", s, s_slice); // hello world hello world
|
println!("{} {}", s, s_slice); // hello world hello world
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ fn main() {
|
|||||||
|
|
||||||
// A slice – an immutable view into a vector or array
|
// A slice – an immutable view into a vector or array
|
||||||
// This is much like a string slice, but for vectors
|
// This is much like a string slice, but for vectors
|
||||||
let slice: &[i32] = &*vector;
|
let slice: &[i32] = &vector;
|
||||||
|
|
||||||
// Use `{:?}` to print something debug-style
|
// Use `{:?}` to print something debug-style
|
||||||
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
|
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
|
||||||
|
@ -5,6 +5,7 @@ contributors:
|
|||||||
- ["George Petrov", "http://github.com/petrovg"]
|
- ["George Petrov", "http://github.com/petrovg"]
|
||||||
- ["Dominic Bou-Samra", "http://dbousamra.github.com"]
|
- ["Dominic Bou-Samra", "http://dbousamra.github.com"]
|
||||||
- ["Geoff Liu", "http://geoffliu.me"]
|
- ["Geoff Liu", "http://geoffliu.me"]
|
||||||
|
- ["Ha-Duong Nguyen", "http://reference-error.org"]
|
||||||
filename: learn.scala
|
filename: learn.scala
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -16,15 +17,16 @@ Scala - the scalable language
|
|||||||
Set yourself up:
|
Set yourself up:
|
||||||
|
|
||||||
1) Download Scala - http://www.scala-lang.org/downloads
|
1) Download Scala - http://www.scala-lang.org/downloads
|
||||||
2) unzip/untar in your favourite location and put the bin subdir on the path
|
2) Unzip/untar to your favourite location and put the bin subdir in your `PATH` environment variable
|
||||||
3) Start a scala REPL by typing scala. You should see the prompt:
|
3) Start a Scala REPL by running `scala`. You should see the prompt:
|
||||||
|
|
||||||
scala>
|
scala>
|
||||||
|
|
||||||
This is the so called REPL (Read-Eval-Print Loop). You may type any valid
|
This is the so called REPL (Read-Eval-Print Loop). You may type any Scala
|
||||||
Scala expression into it, and the result will be printed. We will explain what
|
expression, and the result will be printed. We will explain what Scala files
|
||||||
Scala files look like further into this tutorial, but for now, let's start
|
look like further into this tutorial, but for now, let's start with some
|
||||||
with some basics.
|
basics.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -32,10 +34,10 @@ Scala - the scalable language
|
|||||||
// 1. Basics
|
// 1. Basics
|
||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
|
|
||||||
// Single line comments start with two forward slashes
|
// Single-line comments start with two forward slashes
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Multi line comments, as you can already see from above, look like this.
|
Multi-line comments, as you can already see from above, look like this.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Printing, and forcing a new line on the next print
|
// Printing, and forcing a new line on the next print
|
||||||
@ -46,12 +48,12 @@ println(10)
|
|||||||
print("Hello world")
|
print("Hello world")
|
||||||
|
|
||||||
// Declaring values is done using either var or val.
|
// Declaring values is done using either var or val.
|
||||||
// val declarations are immutable, whereas var's are mutable. Immutability is
|
// val declarations are immutable, whereas vars are mutable. Immutability is
|
||||||
// a good thing.
|
// a good thing.
|
||||||
val x = 10 // x is now 10
|
val x = 10 // x is now 10
|
||||||
x = 20 // error: reassignment to val
|
x = 20 // error: reassignment to val
|
||||||
var y = 10
|
var y = 10
|
||||||
y = 20 // y is now 20
|
y = 20 // y is now 20
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Scala is a statically typed language, yet note that in the above declarations,
|
Scala is a statically typed language, yet note that in the above declarations,
|
||||||
@ -71,17 +73,17 @@ true
|
|||||||
false
|
false
|
||||||
|
|
||||||
// Boolean operations
|
// Boolean operations
|
||||||
!true // false
|
!true // false
|
||||||
!false // true
|
!false // true
|
||||||
true == false // false
|
true == false // false
|
||||||
10 > 5 // true
|
10 > 5 // true
|
||||||
|
|
||||||
// Math is as per usual
|
// Math is as per usual
|
||||||
1 + 1 // 2
|
1 + 1 // 2
|
||||||
2 - 1 // 1
|
2 - 1 // 1
|
||||||
5 * 3 // 15
|
5 * 3 // 15
|
||||||
6 / 2 // 3
|
6 / 2 // 3
|
||||||
6 / 4 // 1
|
6 / 4 // 1
|
||||||
6.0 / 4 // 1.5
|
6.0 / 4 // 1.5
|
||||||
|
|
||||||
|
|
||||||
@ -120,12 +122,12 @@ s"We have $n apples" // => "We have 45 apples"
|
|||||||
|
|
||||||
// Expressions inside interpolated strings are also possible
|
// Expressions inside interpolated strings are also possible
|
||||||
val a = Array(11, 9, 6)
|
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"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"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"
|
s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4"
|
||||||
|
|
||||||
// Formatting with interpolated strings with the prefix "f"
|
// Formatting with interpolated strings with the prefix "f"
|
||||||
f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25"
|
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"
|
f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454"
|
||||||
|
|
||||||
// Raw strings, ignoring special characters.
|
// Raw strings, ignoring special characters.
|
||||||
@ -171,12 +173,12 @@ def sq(x: Int) = x * x // Compiler can guess return type is Int
|
|||||||
|
|
||||||
// Functions can have default parameters:
|
// Functions can have default parameters:
|
||||||
def addWithDefault(x: Int, y: Int = 5) = x + y
|
def addWithDefault(x: Int, y: Int = 5) = x + y
|
||||||
addWithDefault(1, 2) // => 3
|
addWithDefault(1, 2) // => 3
|
||||||
addWithDefault(1) // => 6
|
addWithDefault(1) // => 6
|
||||||
|
|
||||||
|
|
||||||
// Anonymous functions look like this:
|
// Anonymous functions look like this:
|
||||||
(x:Int) => x * x
|
(x: Int) => x * x
|
||||||
|
|
||||||
// Unlike defs, even the input type of anonymous functions can be omitted if the
|
// Unlike defs, even the input type of anonymous functions can be omitted if the
|
||||||
// context makes it clear. Notice the type "Int => Int" which means a function
|
// context makes it clear. Notice the type "Int => Int" which means a function
|
||||||
@ -193,8 +195,8 @@ sq(10) // => 100
|
|||||||
val addOne: Int => Int = _ + 1
|
val addOne: Int => Int = _ + 1
|
||||||
val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3)
|
val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3)
|
||||||
|
|
||||||
addOne(5) // => 6
|
addOne(5) // => 6
|
||||||
weirdSum(2, 4) // => 16
|
weirdSum(2, 4) // => 16
|
||||||
|
|
||||||
|
|
||||||
// The return keyword exists in Scala, but it only returns from the inner-most
|
// The return keyword exists in Scala, but it only returns from the inner-most
|
||||||
@ -204,9 +206,9 @@ weirdSum(2, 4) // => 16
|
|||||||
def foo(x: Int): Int = {
|
def foo(x: Int): Int = {
|
||||||
val anonFunc: Int => Int = { z =>
|
val anonFunc: Int => Int = { z =>
|
||||||
if (z > 5)
|
if (z > 5)
|
||||||
return z // This line makes z the return value of foo!
|
return z // This line makes z the return value of foo!
|
||||||
else
|
else
|
||||||
z + 2 // This line is the return value of anonFunc
|
z + 2 // This line is the return value of anonFunc
|
||||||
}
|
}
|
||||||
anonFunc(x) // This line is the return value of foo
|
anonFunc(x) // This line is the return value of foo
|
||||||
}
|
}
|
||||||
@ -218,19 +220,19 @@ def foo(x: Int): Int = {
|
|||||||
|
|
||||||
1 to 5
|
1 to 5
|
||||||
val r = 1 to 5
|
val r = 1 to 5
|
||||||
r.foreach( println )
|
r.foreach(println)
|
||||||
|
|
||||||
r foreach println
|
r foreach println
|
||||||
// NB: Scala is quite lenient when it comes to dots and brackets - study the
|
// NB: Scala is quite lenient when it comes to dots and brackets - study the
|
||||||
// rules separately. This helps write DSLs and APIs that read like English
|
// rules separately. This helps write DSLs and APIs that read like English
|
||||||
|
|
||||||
(5 to 1 by -1) foreach ( println )
|
(5 to 1 by -1) foreach (println)
|
||||||
|
|
||||||
// A while loops
|
// A while loops
|
||||||
var i = 0
|
var i = 0
|
||||||
while (i < 10) { println("i " + i); i+=1 }
|
while (i < 10) { println("i " + i); i += 1 }
|
||||||
|
|
||||||
while (i < 10) { println("i " + i); i+=1 } // Yes, again. What happened? Why?
|
while (i < 10) { println("i " + i); i += 1 } // Yes, again. What happened? Why?
|
||||||
|
|
||||||
i // Show the value of i. Note that while is a loop in the classical sense -
|
i // Show the value of i. Note that while is a loop in the classical sense -
|
||||||
// it executes sequentially while changing the loop variable. while is very
|
// it executes sequentially while changing the loop variable. while is very
|
||||||
@ -239,19 +241,19 @@ i // Show the value of i. Note that while is a loop in the classical sense -
|
|||||||
|
|
||||||
// A do while loop
|
// A do while loop
|
||||||
do {
|
do {
|
||||||
println("x is still less than 10");
|
println("x is still less than 10")
|
||||||
x += 1
|
x += 1
|
||||||
} while (x < 10)
|
} while (x < 10)
|
||||||
|
|
||||||
// Tail recursion is an idiomatic way of doing recurring things in Scala.
|
// Tail recursion is an idiomatic way of doing recurring things in Scala.
|
||||||
// Recursive functions need an explicit return type, the compiler can't infer it.
|
// Recursive functions need an explicit return type, the compiler can't infer it.
|
||||||
// Here it's Unit.
|
// Here it's Unit.
|
||||||
def showNumbersInRange(a:Int, b:Int):Unit = {
|
def showNumbersInRange(a: Int, b: Int): Unit = {
|
||||||
print(a)
|
print(a)
|
||||||
if (a < b)
|
if (a < b)
|
||||||
showNumbersInRange(a + 1, b)
|
showNumbersInRange(a + 1, b)
|
||||||
}
|
}
|
||||||
showNumbersInRange(1,14)
|
showNumbersInRange(1, 14)
|
||||||
|
|
||||||
|
|
||||||
// Conditionals
|
// Conditionals
|
||||||
@ -305,13 +307,13 @@ s(1)
|
|||||||
(a, 2, "three")
|
(a, 2, "three")
|
||||||
|
|
||||||
// Why have this?
|
// Why have this?
|
||||||
val divideInts = (x:Int, y:Int) => (x / y, x % y)
|
val divideInts = (x: Int, y: Int) => (x / y, x % y)
|
||||||
|
|
||||||
divideInts(10,3) // The function divideInts gives you the result and the remainder
|
divideInts(10, 3) // The function divideInts gives you the result and the remainder
|
||||||
|
|
||||||
// To access the elements of a tuple, use _._n where n is the 1-based index of
|
// To access the elements of a tuple, use _._n where n is the 1-based index of
|
||||||
// the element
|
// the element
|
||||||
val d = divideInts(10,3)
|
val d = divideInts(10, 3)
|
||||||
|
|
||||||
d._1
|
d._1
|
||||||
|
|
||||||
@ -359,7 +361,7 @@ class Dog(br: String) {
|
|||||||
|
|
||||||
val mydog = new Dog("greyhound")
|
val mydog = new Dog("greyhound")
|
||||||
println(mydog.breed) // => "greyhound"
|
println(mydog.breed) // => "greyhound"
|
||||||
println(mydog.bark) // => "Woof, woof!"
|
println(mydog.bark) // => "Woof, woof!"
|
||||||
|
|
||||||
|
|
||||||
// The "object" keyword creates a type AND a singleton instance of it. It is
|
// The "object" keyword creates a type AND a singleton instance of it. It is
|
||||||
@ -414,8 +416,8 @@ val otherGeorge = george.copy(phoneNumber = "9876")
|
|||||||
def matchPerson(person: Person): String = person match {
|
def matchPerson(person: Person): String = person match {
|
||||||
// Then you specify the patterns:
|
// Then you specify the patterns:
|
||||||
case Person("George", number) => "We found George! His number is " + number
|
case Person("George", number) => "We found George! His number is " + number
|
||||||
case Person("Kate", number) => "We found Kate! Her number is " + number
|
case Person("Kate", number) => "We found Kate! Her number is " + number
|
||||||
case Person(name, number) => "We matched someone : " + name + ", phone : " + number
|
case Person(name, number) => "We matched someone : " + name + ", phone : " + number
|
||||||
}
|
}
|
||||||
|
|
||||||
val email = "(.*)@(.*)".r // Define a regex for the next example.
|
val email = "(.*)@(.*)".r // Define a regex for the next example.
|
||||||
@ -446,7 +448,7 @@ def matchEverything(obj: Any): String = obj match {
|
|||||||
case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"
|
case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"
|
||||||
|
|
||||||
// You can nest patterns:
|
// You can nest patterns:
|
||||||
case List(List((1, 2,"YAY"))) => "Got a list of list of tuple"
|
case List(List((1, 2, "YAY"))) => "Got a list of list of tuple"
|
||||||
}
|
}
|
||||||
|
|
||||||
// In fact, you can pattern match any object with an "unapply" method. This
|
// In fact, you can pattern match any object with an "unapply" method. This
|
||||||
@ -493,7 +495,7 @@ sSquared.reduce (_+_)
|
|||||||
// The filter function takes a predicate (a function from A -> Boolean) and
|
// The filter function takes a predicate (a function from A -> Boolean) and
|
||||||
// selects all elements which satisfy the predicate
|
// selects all elements which satisfy the predicate
|
||||||
List(1, 2, 3) filter (_ > 2) // List(3)
|
List(1, 2, 3) filter (_ > 2) // List(3)
|
||||||
case class Person(name:String, age:Int)
|
case class Person(name: String, age: Int)
|
||||||
List(
|
List(
|
||||||
Person(name = "Dom", age = 23),
|
Person(name = "Dom", age = 23),
|
||||||
Person(name = "Bob", age = 30)
|
Person(name = "Bob", age = 30)
|
||||||
@ -541,8 +543,8 @@ implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed)
|
|||||||
|
|
||||||
// By itself, implicit keyword doesn't change the behavior of the value, so
|
// By itself, implicit keyword doesn't change the behavior of the value, so
|
||||||
// above values can be used as usual.
|
// above values can be used as usual.
|
||||||
myImplicitInt + 2 // => 102
|
myImplicitInt + 2 // => 102
|
||||||
myImplicitFunction("Pitbull").breed // => "Golden Pitbull"
|
myImplicitFunction("Pitbull").breed // => "Golden Pitbull"
|
||||||
|
|
||||||
// The difference is that these values are now eligible to be used when another
|
// The difference is that these values are now eligible to be used when another
|
||||||
// piece of code "needs" an implicit value. One such situation is implicit
|
// piece of code "needs" an implicit value. One such situation is implicit
|
||||||
@ -570,8 +572,8 @@ def foo[T : C] = ...
|
|||||||
// implicit conversion of type A => B, where A is the type of obj, and B has a
|
// implicit conversion of type A => B, where A is the type of obj, and B has a
|
||||||
// method called "method", that conversion is applied. So having
|
// method called "method", that conversion is applied. So having
|
||||||
// myImplicitFunction above in scope, we can say:
|
// myImplicitFunction above in scope, we can say:
|
||||||
"Retriever".breed // => "Golden Retriever"
|
"Retriever".breed // => "Golden Retriever"
|
||||||
"Sheperd".bark // => "Woof, woof!"
|
"Sheperd".bark // => "Woof, woof!"
|
||||||
|
|
||||||
// Here the String is first converted to Dog using our function above, and then
|
// Here the String is first converted to Dog using our function above, and then
|
||||||
// the appropriate method is called. This is an extremely powerful feature, but
|
// the appropriate method is called. This is an extremely powerful feature, but
|
||||||
@ -594,7 +596,7 @@ import scala.collection.immutable._
|
|||||||
import scala.collection.immutable.{List, Map}
|
import scala.collection.immutable.{List, Map}
|
||||||
|
|
||||||
// Rename an import using '=>'
|
// Rename an import using '=>'
|
||||||
import scala.collection.immutable.{ List => ImmutableList }
|
import scala.collection.immutable.{List => ImmutableList}
|
||||||
|
|
||||||
// Import all classes, except some. The following excludes Map and Set:
|
// Import all classes, except some. The following excludes Map and Set:
|
||||||
import scala.collection.immutable.{Map => _, Set => _, _}
|
import scala.collection.immutable.{Map => _, Set => _, _}
|
||||||
@ -629,13 +631,8 @@ writer.close()
|
|||||||
|
|
||||||
## Further resources
|
## Further resources
|
||||||
|
|
||||||
[Scala for the impatient](http://horstmann.com/scala/)
|
* [Scala for the impatient](http://horstmann.com/scala/)
|
||||||
|
* [Twitter Scala school](http://twitter.github.io/scala_school/)
|
||||||
[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/)
|
||||||
[The scala documentation](http://docs.scala-lang.org/)
|
* Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user)
|
||||||
|
|
||||||
[Try Scala in your browser](http://scalatutorials.com/tour/)
|
|
||||||
|
|
||||||
Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user)
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ contributors:
|
|||||||
- ["Grant Timmerman", "http://github.com/grant"]
|
- ["Grant Timmerman", "http://github.com/grant"]
|
||||||
- ["Christopher Bess", "http://github.com/cbess"]
|
- ["Christopher Bess", "http://github.com/cbess"]
|
||||||
- ["Joey Huang", "http://github.com/kamidox"]
|
- ["Joey Huang", "http://github.com/kamidox"]
|
||||||
|
- ["Anthony Nguyen", "http://github.com/anthonyn60"]
|
||||||
filename: learnswift.swift
|
filename: learnswift.swift
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -26,7 +27,9 @@ import UIKit
|
|||||||
// TODO: Do something soon
|
// TODO: Do something soon
|
||||||
// FIXME: Fix this code
|
// FIXME: Fix this code
|
||||||
|
|
||||||
println("Hello, world")
|
// In Swift 2, println and print were combined into one print method. Print automatically appends a new line.
|
||||||
|
print("Hello, world") // println is now print
|
||||||
|
print("Hello, world", appendNewLine: false) // printing without appending a newline
|
||||||
|
|
||||||
// variables (var) value can change after being set
|
// variables (var) value can change after being set
|
||||||
// constants (let) value can NOT be changed after being set
|
// constants (let) value can NOT be changed after being set
|
||||||
@ -46,12 +49,12 @@ let piText = "Pi = \(π), Pi 2 = \(π * 2)" // String interpolation
|
|||||||
// Build Specific values
|
// Build Specific values
|
||||||
// uses -D build configuration
|
// uses -D build configuration
|
||||||
#if false
|
#if false
|
||||||
println("Not printed")
|
print("Not printed")
|
||||||
let buildValue = 3
|
let buildValue = 3
|
||||||
#else
|
#else
|
||||||
let buildValue = 7
|
let buildValue = 7
|
||||||
#endif
|
#endif
|
||||||
println("Build value: \(buildValue)") // Build value: 7
|
print("Build value: \(buildValue)") // Build value: 7
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Optionals are a Swift language feature that allows you to store a `Some` or
|
Optionals are a Swift language feature that allows you to store a `Some` or
|
||||||
@ -69,7 +72,7 @@ var someOptionalString2: Optional<String> = "optional"
|
|||||||
if someOptionalString != nil {
|
if someOptionalString != nil {
|
||||||
// I am not nil
|
// I am not nil
|
||||||
if someOptionalString!.hasPrefix("opt") {
|
if someOptionalString!.hasPrefix("opt") {
|
||||||
println("has the prefix")
|
print("has the prefix")
|
||||||
}
|
}
|
||||||
|
|
||||||
let empty = someOptionalString?.isEmpty
|
let empty = someOptionalString?.isEmpty
|
||||||
@ -138,21 +141,21 @@ var emptyMutableDictionary = [String: Float]() // var == mutable
|
|||||||
let myArray = [1, 1, 2, 3, 5]
|
let myArray = [1, 1, 2, 3, 5]
|
||||||
for value in myArray {
|
for value in myArray {
|
||||||
if value == 1 {
|
if value == 1 {
|
||||||
println("One!")
|
print("One!")
|
||||||
} else {
|
} else {
|
||||||
println("Not one!")
|
print("Not one!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for loop (dictionary)
|
// for loop (dictionary)
|
||||||
var dict = ["one": 1, "two": 2]
|
var dict = ["one": 1, "two": 2]
|
||||||
for (key, value) in dict {
|
for (key, value) in dict {
|
||||||
println("\(key): \(value)")
|
print("\(key): \(value)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// for loop (range)
|
// for loop (range)
|
||||||
for i in -1...shoppingList.count {
|
for i in -1...shoppingList.count {
|
||||||
println(i)
|
print(i)
|
||||||
}
|
}
|
||||||
shoppingList[1...2] = ["steak", "peacons"]
|
shoppingList[1...2] = ["steak", "peacons"]
|
||||||
// use ..< to exclude the last number
|
// use ..< to exclude the last number
|
||||||
@ -165,7 +168,7 @@ while i < 1000 {
|
|||||||
|
|
||||||
// do-while loop
|
// do-while loop
|
||||||
do {
|
do {
|
||||||
println("hello")
|
print("hello")
|
||||||
} while 1 == 2
|
} while 1 == 2
|
||||||
|
|
||||||
// Switch
|
// Switch
|
||||||
@ -222,8 +225,8 @@ let pricesTuple = getGasPrices()
|
|||||||
let price = pricesTuple.2 // 3.79
|
let price = pricesTuple.2 // 3.79
|
||||||
// Ignore Tuple (or other) values by using _ (underscore)
|
// Ignore Tuple (or other) values by using _ (underscore)
|
||||||
let (_, price1, _) = pricesTuple // price1 == 3.69
|
let (_, price1, _) = pricesTuple // price1 == 3.69
|
||||||
println(price1 == pricesTuple.1) // true
|
print(price1 == pricesTuple.1) // true
|
||||||
println("Gas price: \(price)")
|
print("Gas price: \(price)")
|
||||||
|
|
||||||
// Variadic Args
|
// Variadic Args
|
||||||
func setup(numbers: Int...) {
|
func setup(numbers: Int...) {
|
||||||
@ -251,7 +254,7 @@ func swapTwoInts(inout a: Int, inout b: Int) {
|
|||||||
var someIntA = 7
|
var someIntA = 7
|
||||||
var someIntB = 3
|
var someIntB = 3
|
||||||
swapTwoInts(&someIntA, &someIntB)
|
swapTwoInts(&someIntA, &someIntB)
|
||||||
println(someIntB) // 7
|
print(someIntB) // 7
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -305,7 +308,7 @@ struct NamesTable {
|
|||||||
// Structures have an auto-generated (implicit) designated initializer
|
// Structures have an auto-generated (implicit) designated initializer
|
||||||
let namesTable = NamesTable(names: ["Me", "Them"])
|
let namesTable = NamesTable(names: ["Me", "Them"])
|
||||||
let name = namesTable[1]
|
let name = namesTable[1]
|
||||||
println("Name is \(name)") // Name is Them
|
print("Name is \(name)") // Name is Them
|
||||||
|
|
||||||
//
|
//
|
||||||
// MARK: Classes
|
// MARK: Classes
|
||||||
@ -386,7 +389,7 @@ let aShape = mySquare as Shape
|
|||||||
|
|
||||||
// compare instances, not the same as == which compares objects (equal to)
|
// compare instances, not the same as == which compares objects (equal to)
|
||||||
if mySquare === mySquare {
|
if mySquare === mySquare {
|
||||||
println("Yep, it's mySquare")
|
print("Yep, it's mySquare")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional init
|
// Optional init
|
||||||
@ -409,13 +412,13 @@ class Circle: Shape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var myCircle = Circle(radius: 1)
|
var myCircle = Circle(radius: 1)
|
||||||
println(myCircle?.getArea()) // Optional(3)
|
print(myCircle?.getArea()) // Optional(3)
|
||||||
println(myCircle!.getArea()) // 3
|
print(myCircle!.getArea()) // 3
|
||||||
var myEmptyCircle = Circle(radius: -1)
|
var myEmptyCircle = Circle(radius: -1)
|
||||||
println(myEmptyCircle?.getArea()) // "nil"
|
print(myEmptyCircle?.getArea()) // "nil"
|
||||||
if let circle = myEmptyCircle {
|
if let circle = myEmptyCircle {
|
||||||
// will not execute since myEmptyCircle is nil
|
// will not execute since myEmptyCircle is nil
|
||||||
println("circle is not nil")
|
print("circle is not nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -447,7 +450,7 @@ enum BookName: String {
|
|||||||
case John = "John"
|
case John = "John"
|
||||||
case Luke = "Luke"
|
case Luke = "Luke"
|
||||||
}
|
}
|
||||||
println("Name: \(BookName.John.rawValue)")
|
print("Name: \(BookName.John.rawValue)")
|
||||||
|
|
||||||
// Enum with associated Values
|
// Enum with associated Values
|
||||||
enum Furniture {
|
enum Furniture {
|
||||||
@ -467,9 +470,9 @@ enum Furniture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var desk: Furniture = .Desk(height: 80)
|
var desk: Furniture = .Desk(height: 80)
|
||||||
println(desk.description()) // "Desk with 80 cm"
|
print(desk.description()) // "Desk with 80 cm"
|
||||||
var chair = Furniture.Chair("Foo", 40)
|
var chair = Furniture.Chair("Foo", 40)
|
||||||
println(chair.description()) // "Chair of Foo with 40 cm"
|
print(chair.description()) // "Chair of Foo with 40 cm"
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -522,7 +525,7 @@ extension Square: Printable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Square: \(mySquare)")
|
print("Square: \(mySquare)")
|
||||||
|
|
||||||
// You can also extend built-in types
|
// You can also extend built-in types
|
||||||
extension Int {
|
extension Int {
|
||||||
@ -535,8 +538,8 @@ extension Int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println(7.customProperty) // "This is 7"
|
print(7.customProperty) // "This is 7"
|
||||||
println(14.multiplyBy(3)) // 42
|
print(14.multiplyBy(3)) // 42
|
||||||
|
|
||||||
// Generics: Similar to Java and C#. Use the `where` keyword to specify the
|
// Generics: Similar to Java and C#. Use the `where` keyword to specify the
|
||||||
// requirements of the generics.
|
// requirements of the generics.
|
||||||
@ -550,7 +553,7 @@ func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let foundAtIndex = findIndex([1, 2, 3, 4], 3)
|
let foundAtIndex = findIndex([1, 2, 3, 4], 3)
|
||||||
println(foundAtIndex == 2) // true
|
print(foundAtIndex == 2) // true
|
||||||
|
|
||||||
// Operators:
|
// Operators:
|
||||||
// Custom operators can start with the characters:
|
// Custom operators can start with the characters:
|
||||||
@ -566,9 +569,9 @@ prefix func !!! (inout shape: Square) -> Square {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// current value
|
// current value
|
||||||
println(mySquare.sideLength) // 4
|
print(mySquare.sideLength) // 4
|
||||||
|
|
||||||
// change side length using custom !!! operator, increases size by 3
|
// change side length using custom !!! operator, increases size by 3
|
||||||
!!!mySquare
|
!!!mySquare
|
||||||
println(mySquare.sideLength) // 12
|
print(mySquare.sideLength) // 12
|
||||||
```
|
```
|
||||||
|
12
tcl.html.markdown
Executable file → Normal file
12
tcl.html.markdown
Executable file → Normal file
@ -121,7 +121,8 @@ puts lots\nof\n\n\n\n\n\nnewlines
|
|||||||
|
|
||||||
|
|
||||||
# A word enclosed in braces is not subject to any special interpretation or
|
# A word enclosed in braces is not subject to any special interpretation or
|
||||||
# substitutions, except that a backslash before a brace is not counted when look#ing for the closing brace
|
# substitutions, except that a backslash before a brace is not counted when
|
||||||
|
# looking for the closing brace
|
||||||
set somevar {
|
set somevar {
|
||||||
This is a literal $ sign, and this \} escaped
|
This is a literal $ sign, and this \} escaped
|
||||||
brace remains uninterpreted
|
brace remains uninterpreted
|
||||||
@ -163,7 +164,7 @@ set greeting "Hello, $person(name)"
|
|||||||
# A namespace holds commands and variables
|
# A namespace holds commands and variables
|
||||||
namespace eval people {
|
namespace eval people {
|
||||||
namespace eval person1 {
|
namespace eval person1 {
|
||||||
set name Neo
|
variable name Neo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +190,10 @@ set greeting "Hello $people::person1::name"
|
|||||||
namespace delete ::
|
namespace delete ::
|
||||||
|
|
||||||
|
|
||||||
# Because of name resolution behaviour, it's safer to use the "variable" command to declare or to assign a value to a namespace.
|
# Because of name resolution behaviour, it's safer to use the "variable" command to
|
||||||
|
# declare or to assign a value to a namespace. If a variable called "name" already
|
||||||
|
# exists in the global namespace, using "set" here will assign a value to the global variable
|
||||||
|
# instead of creating a new variable in the local namespace.
|
||||||
namespace eval people {
|
namespace eval people {
|
||||||
namespace eval person1 {
|
namespace eval person1 {
|
||||||
variable name Neo
|
variable name Neo
|
||||||
@ -256,7 +260,7 @@ proc greet greeting\ name return\ \"Hello,\ \$name!
|
|||||||
proc fold {cmd args} {
|
proc fold {cmd args} {
|
||||||
set res 0
|
set res 0
|
||||||
foreach arg $args {
|
foreach arg $args {
|
||||||
set res [cmd $res $arg]
|
set res [$cmd $res $arg]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fold ::tcl::mathop::* 5 3 3 ;# -> 45
|
fold ::tcl::mathop::* 5 3 3 ;# -> 45
|
||||||
|
@ -8,7 +8,7 @@ contributors:
|
|||||||
translators:
|
translators:
|
||||||
- ["Melih Mucuk", "http://melihmucuk.com"]
|
- ["Melih Mucuk", "http://melihmucuk.com"]
|
||||||
lang: tr-tr
|
lang: tr-tr
|
||||||
filename: LearnCSharp.cs
|
filename: LearnCSharp-tr.cs
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -283,4 +283,4 @@ Go的根源在[Go官方网站](http://golang.org/)。
|
|||||||
|
|
||||||
强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.)
|
强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.)
|
||||||
|
|
||||||
学习Go还要阅读Go标准库的源代码,全部文档化了,可读性非常好,可以学到go,go style和go idioms。在文档中点击函数名,源代码就出来了!
|
学习Go还要阅读Go[标准库的源代码](http://golang.org/src/),全部文档化了,可读性非常好,可以学到go,go style和go idioms。在[文档](http://golang.org/pkg/)中点击函数名,源代码就出来了!
|
||||||
|
420
zh-cn/groovy-cn.html.markdown
Normal file
420
zh-cn/groovy-cn.html.markdown
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
---
|
||||||
|
language: Groovy
|
||||||
|
filename: learngroovy-cn.groovy
|
||||||
|
contributors:
|
||||||
|
- ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"]
|
||||||
|
translators:
|
||||||
|
- ["Todd Gao", "http://github.com/7c00"]
|
||||||
|
lang: zh-cn
|
||||||
|
---
|
||||||
|
|
||||||
|
Groovy - Java平台的动态语言。[了解更多。](http://www.groovy-lang.org/)
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
|
||||||
|
/*
|
||||||
|
安装:
|
||||||
|
|
||||||
|
1) 安装 GVM - http://gvmtool.net/
|
||||||
|
2) 安装 Groovy: gvm install groovy
|
||||||
|
3) 启动 groovy 控制台,键入: groovyConsole
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 双斜线开始的是单行注释
|
||||||
|
/*
|
||||||
|
像这样的是多行注释
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Hello World
|
||||||
|
println "Hello world!"
|
||||||
|
|
||||||
|
/*
|
||||||
|
变量:
|
||||||
|
|
||||||
|
可以给变量赋值,以便稍后使用
|
||||||
|
*/
|
||||||
|
|
||||||
|
def x = 1
|
||||||
|
println x
|
||||||
|
|
||||||
|
x = new java.util.Date()
|
||||||
|
println x
|
||||||
|
|
||||||
|
x = -3.1499392
|
||||||
|
println x
|
||||||
|
|
||||||
|
x = false
|
||||||
|
println x
|
||||||
|
|
||||||
|
x = "Groovy!"
|
||||||
|
println x
|
||||||
|
|
||||||
|
/*
|
||||||
|
集合和映射
|
||||||
|
*/
|
||||||
|
|
||||||
|
//创建一个空的列表
|
||||||
|
def technologies = []
|
||||||
|
|
||||||
|
/*** 往列表中增加一个元素 ***/
|
||||||
|
|
||||||
|
// 和Java一样
|
||||||
|
technologies.add("Grails")
|
||||||
|
|
||||||
|
// 左移添加,返回该列表
|
||||||
|
technologies << "Groovy"
|
||||||
|
|
||||||
|
// 增加多个元素
|
||||||
|
technologies.addAll(["Gradle","Griffon"])
|
||||||
|
|
||||||
|
/*** 从列表中删除元素 ***/
|
||||||
|
|
||||||
|
// 和Java一样
|
||||||
|
technologies.remove("Griffon")
|
||||||
|
|
||||||
|
// 减号也行
|
||||||
|
technologies = technologies - 'Grails'
|
||||||
|
|
||||||
|
/*** 遍历列表 ***/
|
||||||
|
|
||||||
|
// 遍历列表中的元素
|
||||||
|
technologies.each { println "Technology: $it"}
|
||||||
|
technologies.eachWithIndex { it, i -> println "$i: $it"}
|
||||||
|
|
||||||
|
/*** 检查列表内容 ***/
|
||||||
|
|
||||||
|
//判断列表是否包含某元素,返回boolean
|
||||||
|
contained = technologies.contains( 'Groovy' )
|
||||||
|
|
||||||
|
// 或
|
||||||
|
contained = 'Groovy' in technologies
|
||||||
|
|
||||||
|
// 检查多个元素
|
||||||
|
technologies.containsAll(['Groovy','Grails'])
|
||||||
|
|
||||||
|
/*** 列表排序 ***/
|
||||||
|
|
||||||
|
// 排序列表(修改原列表)
|
||||||
|
technologies.sort()
|
||||||
|
|
||||||
|
// 要想不修改原列表,可以这样:
|
||||||
|
sortedTechnologies = technologies.sort( false )
|
||||||
|
|
||||||
|
/*** 列表操作 ***/
|
||||||
|
|
||||||
|
//替换列表元素
|
||||||
|
Collections.replaceAll(technologies, 'Gradle', 'gradle')
|
||||||
|
|
||||||
|
//打乱列表
|
||||||
|
Collections.shuffle(technologies, new Random())
|
||||||
|
|
||||||
|
//清空列表
|
||||||
|
technologies.clear()
|
||||||
|
|
||||||
|
//创建空的映射
|
||||||
|
def devMap = [:]
|
||||||
|
|
||||||
|
//增加值
|
||||||
|
devMap = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']
|
||||||
|
devMap.put('lastName','Perez')
|
||||||
|
|
||||||
|
//遍历映射元素
|
||||||
|
devMap.each { println "$it.key: $it.value" }
|
||||||
|
devMap.eachWithIndex { it, i -> println "$i: $it"}
|
||||||
|
|
||||||
|
//判断映射是否包含某键
|
||||||
|
assert devMap.containsKey('name')
|
||||||
|
|
||||||
|
//判断映射是否包含某值
|
||||||
|
assert devMap.containsValue('Roberto')
|
||||||
|
|
||||||
|
//取得映射所有的键
|
||||||
|
println devMap.keySet()
|
||||||
|
|
||||||
|
//取得映射所有的值
|
||||||
|
println devMap.values()
|
||||||
|
|
||||||
|
/*
|
||||||
|
Groovy Beans
|
||||||
|
|
||||||
|
GroovyBeans 是 JavaBeans,但使用了更简单的语法
|
||||||
|
|
||||||
|
Groovy 被编译为字节码时,遵循下列规则。
|
||||||
|
|
||||||
|
* 如果一个名字声明时带有访问修饰符(public, private, 或者 protected),
|
||||||
|
则会生成一个字段(field)。
|
||||||
|
|
||||||
|
* 名字声明时没有访问修饰符,则会生成一个带有public getter和setter的
|
||||||
|
private字段,即属性(property)。
|
||||||
|
|
||||||
|
* 如果一个属性声明为final,则会创建一个final的private字段,但不会生成setter。
|
||||||
|
|
||||||
|
* 可以声明一个属性的同时定义自己的getter和setter。
|
||||||
|
|
||||||
|
* 可以声明具有相同名字的属性和字段,该属性会使用该字段。
|
||||||
|
|
||||||
|
* 如果要定义private或protected属性,必须提供声明为private或protected的getter
|
||||||
|
和setter。
|
||||||
|
|
||||||
|
* 如果使用显式或隐式的 this(例如 this.foo, 或者 foo)访问类的在编译时定义的属性,
|
||||||
|
Groovy会直接访问对应字段,而不是使用getter或者setter
|
||||||
|
|
||||||
|
* 如果使用显式或隐式的 foo 访问一个不存在的属性,Groovy会通过元类(meta class)
|
||||||
|
访问它,这可能导致运行时错误。
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
// 只读属性
|
||||||
|
final String name = "Roberto"
|
||||||
|
|
||||||
|
// 只读属性,有public getter和protected setter
|
||||||
|
String language
|
||||||
|
protected void setLanguage(String language) { this.language = language }
|
||||||
|
|
||||||
|
// 动态类型属性
|
||||||
|
def lastName
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
逻辑分支和循环
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Groovy支持常见的if - else语法
|
||||||
|
def x = 3
|
||||||
|
|
||||||
|
if(x==1) {
|
||||||
|
println "One"
|
||||||
|
} else if(x==2) {
|
||||||
|
println "Two"
|
||||||
|
} else {
|
||||||
|
println "X greater than Two"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Groovy也支持三元运算符
|
||||||
|
def y = 10
|
||||||
|
def x = (y > 1) ? "worked" : "failed"
|
||||||
|
assert x == "worked"
|
||||||
|
|
||||||
|
//for循环
|
||||||
|
//使用区间(range)遍历
|
||||||
|
def x = 0
|
||||||
|
for (i in 0 .. 30) {
|
||||||
|
x += i
|
||||||
|
}
|
||||||
|
|
||||||
|
//遍历列表
|
||||||
|
x = 0
|
||||||
|
for( i in [5,3,2,1] ) {
|
||||||
|
x += i
|
||||||
|
}
|
||||||
|
|
||||||
|
//遍历数组
|
||||||
|
array = (0..20).toArray()
|
||||||
|
x = 0
|
||||||
|
for (i in array) {
|
||||||
|
x += i
|
||||||
|
}
|
||||||
|
|
||||||
|
//遍历映射
|
||||||
|
def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']
|
||||||
|
x = 0
|
||||||
|
for ( e in map ) {
|
||||||
|
x += e.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
运算符
|
||||||
|
|
||||||
|
在Groovy中以下常用运算符支持重载:
|
||||||
|
http://www.groovy-lang.org/operators.html#Operator-Overloading
|
||||||
|
|
||||||
|
实用的groovy运算符
|
||||||
|
*/
|
||||||
|
//展开(spread)运算符:对聚合对象的所有元素施加操作
|
||||||
|
def technologies = ['Groovy','Grails','Gradle']
|
||||||
|
technologies*.toUpperCase() // 相当于 technologies.collect { it?.toUpperCase() }
|
||||||
|
|
||||||
|
//安全导航(safe navigation)运算符:用来避免NullPointerException
|
||||||
|
def user = User.get(1)
|
||||||
|
def username = user?.username
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
闭包
|
||||||
|
Groovy闭包好比代码块或者方法指针,它是一段代码定义,可以以后执行。
|
||||||
|
|
||||||
|
更多信息见:http://www.groovy-lang.org/closures.html
|
||||||
|
*/
|
||||||
|
//例子:
|
||||||
|
def clos = { println "Hello World!" }
|
||||||
|
|
||||||
|
println "Executing the Closure:"
|
||||||
|
clos()
|
||||||
|
|
||||||
|
//传参数给闭包
|
||||||
|
def sum = { a, b -> println a+b }
|
||||||
|
sum(2,4)
|
||||||
|
|
||||||
|
//闭包可以引用参数列表以外的变量
|
||||||
|
def x = 5
|
||||||
|
def multiplyBy = { num -> num * x }
|
||||||
|
println multiplyBy(10)
|
||||||
|
|
||||||
|
// 只有一个参数的闭包可以省略参数的定义
|
||||||
|
def clos = { print it }
|
||||||
|
clos( "hi" )
|
||||||
|
|
||||||
|
/*
|
||||||
|
Groovy可以记忆闭包结果 [1][2][3]
|
||||||
|
*/
|
||||||
|
def cl = {a, b ->
|
||||||
|
sleep(3000) // 模拟费时操作
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
mem = cl.memoize()
|
||||||
|
|
||||||
|
def callClosure(a, b) {
|
||||||
|
def start = System.currentTimeMillis()
|
||||||
|
mem(a, b)
|
||||||
|
println "Inputs(a = $a, b = $b) - took ${System.currentTimeMillis() - start} msecs."
|
||||||
|
}
|
||||||
|
|
||||||
|
callClosure(1, 2)
|
||||||
|
callClosure(1, 2)
|
||||||
|
callClosure(2, 3)
|
||||||
|
callClosure(2, 3)
|
||||||
|
callClosure(3, 4)
|
||||||
|
callClosure(3, 4)
|
||||||
|
callClosure(1, 2)
|
||||||
|
callClosure(2, 3)
|
||||||
|
callClosure(3, 4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Expando
|
||||||
|
|
||||||
|
Expando类是一种动态bean类,可以给它的实例添加属性和添加闭包作为方法
|
||||||
|
|
||||||
|
http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html
|
||||||
|
*/
|
||||||
|
def user = new Expando(name:"Roberto")
|
||||||
|
assert 'Roberto' == user.name
|
||||||
|
|
||||||
|
user.lastName = 'Pérez'
|
||||||
|
assert 'Pérez' == user.lastName
|
||||||
|
|
||||||
|
user.showInfo = { out ->
|
||||||
|
out << "Name: $name"
|
||||||
|
out << ", Last name: $lastName"
|
||||||
|
}
|
||||||
|
|
||||||
|
def sw = new StringWriter()
|
||||||
|
println user.showInfo(sw)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
元编程(MOP)
|
||||||
|
*/
|
||||||
|
|
||||||
|
//使用ExpandoMetaClass增加行为
|
||||||
|
String.metaClass.testAdd = {
|
||||||
|
println "we added this"
|
||||||
|
}
|
||||||
|
|
||||||
|
String x = "test"
|
||||||
|
x?.testAdd()
|
||||||
|
|
||||||
|
//拦截方法调用
|
||||||
|
class Test implements GroovyInterceptable {
|
||||||
|
def sum(Integer x, Integer y) { x + y }
|
||||||
|
|
||||||
|
def invokeMethod(String name, args) {
|
||||||
|
System.out.println "Invoke method $name with args: $args"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def test = new Test()
|
||||||
|
test?.sum(2,3)
|
||||||
|
test?.multiply(2,3)
|
||||||
|
|
||||||
|
//Groovy支持propertyMissing,来处理属性解析尝试
|
||||||
|
class Foo {
|
||||||
|
def propertyMissing(String name) { name }
|
||||||
|
}
|
||||||
|
def f = new Foo()
|
||||||
|
|
||||||
|
assertEquals "boo", f.boo
|
||||||
|
|
||||||
|
/*
|
||||||
|
类型检查和静态编译
|
||||||
|
Groovy天生是并将永远是一门动态语言,但也支持类型检查和静态编译
|
||||||
|
|
||||||
|
更多: http://www.infoq.com/articles/new-groovy-20
|
||||||
|
*/
|
||||||
|
//类型检查
|
||||||
|
import groovy.transform.TypeChecked
|
||||||
|
|
||||||
|
void testMethod() {}
|
||||||
|
|
||||||
|
@TypeChecked
|
||||||
|
void test() {
|
||||||
|
testMeethod()
|
||||||
|
|
||||||
|
def name = "Roberto"
|
||||||
|
|
||||||
|
println naameee
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//另一例子
|
||||||
|
import groovy.transform.TypeChecked
|
||||||
|
|
||||||
|
@TypeChecked
|
||||||
|
Integer test() {
|
||||||
|
Integer num = "1"
|
||||||
|
|
||||||
|
Integer[] numbers = [1,2,3,4]
|
||||||
|
|
||||||
|
Date date = numbers[1]
|
||||||
|
|
||||||
|
return "Test"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//静态编译例子
|
||||||
|
import groovy.transform.CompileStatic
|
||||||
|
|
||||||
|
@CompileStatic
|
||||||
|
int sum(int x, int y) {
|
||||||
|
x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
assert sum(2,5) == 7
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## 进阶资源
|
||||||
|
|
||||||
|
[Groovy文档](http://www.groovy-lang.org/documentation.html)
|
||||||
|
|
||||||
|
[Groovy web console](http://groovyconsole.appspot.com/)
|
||||||
|
|
||||||
|
加入[Groovy用户组](http://www.groovy-lang.org/usergroups.html)
|
||||||
|
|
||||||
|
## 图书
|
||||||
|
|
||||||
|
* [Groovy Goodness] (https://leanpub.com/groovy-goodness-notebook)
|
||||||
|
|
||||||
|
* [Groovy in Action] (http://manning.com/koenig2/)
|
||||||
|
|
||||||
|
* [Programming Groovy 2: Dynamic Productivity for the Java Developer] (http://shop.oreilly.com/product/9781937785307.do)
|
||||||
|
|
||||||
|
[1] http://roshandawrani.wordpress.com/2010/10/18/groovy-new-feature-closures-can-now-memorize-their-results/
|
||||||
|
[2] http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize
|
||||||
|
[3] http://mrhaki.blogspot.mx/2011/05/groovy-goodness-cache-closure-results.html
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -149,7 +149,7 @@ public class LearnJava {
|
|||||||
|
|
||||||
// 位运算操作符
|
// 位运算操作符
|
||||||
/*
|
/*
|
||||||
~ 补
|
~ 取反,求反码
|
||||||
<< 带符号左移
|
<< 带符号左移
|
||||||
>> 带符号右移
|
>> 带符号右移
|
||||||
>>> 无符号右移
|
>>> 无符号右移
|
||||||
|
@ -7,6 +7,7 @@ contributors:
|
|||||||
- ["Joel Walden", "http://joelwalden.net"]
|
- ["Joel Walden", "http://joelwalden.net"]
|
||||||
- ["Luke Holder", "http://twitter.com/lukeholder"]
|
- ["Luke Holder", "http://twitter.com/lukeholder"]
|
||||||
- ["lidashuang", "https://github.com/lidashuang"]
|
- ["lidashuang", "https://github.com/lidashuang"]
|
||||||
|
- ["ftwbzhao", "https://github.com/ftwbzhao"]
|
||||||
translators:
|
translators:
|
||||||
- ["Lin Xiangyu", "https://github.com/oa414"]
|
- ["Lin Xiangyu", "https://github.com/oa414"]
|
||||||
---
|
---
|
||||||
@ -120,11 +121,11 @@ status == :approved #=> false
|
|||||||
# 数组
|
# 数组
|
||||||
|
|
||||||
# 这是一个数组
|
# 这是一个数组
|
||||||
[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
|
array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
|
||||||
|
|
||||||
# 数组可以包含不同类型的元素
|
# 数组可以包含不同类型的元素
|
||||||
|
|
||||||
array = [1, "hello", false] #=> => [1, "hello", false]
|
[1, "hello", false] #=> [1, "hello", false]
|
||||||
|
|
||||||
# 数组可以被索引
|
# 数组可以被索引
|
||||||
# 从前面开始
|
# 从前面开始
|
||||||
@ -140,8 +141,8 @@ array.[] 12 #=> nil
|
|||||||
# 从尾部开始
|
# 从尾部开始
|
||||||
array[-1] #=> 5
|
array[-1] #=> 5
|
||||||
|
|
||||||
# 同时指定开始的位置和结束的位置
|
# 同时指定开始的位置和长度
|
||||||
array[2, 4] #=> [3, 4, 5]
|
array[2, 3] #=> [3, 4, 5]
|
||||||
|
|
||||||
# 或者指定一个范围
|
# 或者指定一个范围
|
||||||
array[1..3] #=> [2, 3, 4]
|
array[1..3] #=> [2, 3, 4]
|
||||||
|
296
zh-cn/rust-cn.html.markdown
Normal file
296
zh-cn/rust-cn.html.markdown
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
---
|
||||||
|
language: rust
|
||||||
|
contributors:
|
||||||
|
- ["P1start", "http://p1start.github.io/"]
|
||||||
|
translators:
|
||||||
|
- ["Guangming Mao", "http://maogm.com"]
|
||||||
|
filename: learnrust-cn.rs
|
||||||
|
lang: zh-cn
|
||||||
|
---
|
||||||
|
|
||||||
|
Rust 是由 Mozilla 研究院开发的编程语言。Rust 将底层的性能控制与高级语言的便利性和安全保障结合在了一起。
|
||||||
|
|
||||||
|
而 Rust 并不需要一个垃圾回收器或者运行时即可实现这个目的,这使得 Rust 库可以成为一种 C 语言的替代品。
|
||||||
|
|
||||||
|
Rust 第一版(0.1 版)发布于 2012 年 1 月,3 年以来一直在紧锣密鼓地迭代。
|
||||||
|
因为更新太频繁,一般建议使用每夜构建版而不是稳定版,直到最近 1.0 版本的发布。
|
||||||
|
|
||||||
|
2015 年 3 月 15 日,Rust 1.0 发布,完美向后兼容,最新的每夜构建版提供了缩短编译时间等新特性。
|
||||||
|
Rust 采用了持续迭代模型,每 6 周一个发布版。Rust 1.1 beta 版在 1.0 发布时同时发布。
|
||||||
|
|
||||||
|
尽管 Rust 相对来说是一门底层语言,它提供了一些常见于高级语言的函数式编程的特性。这让 Rust 不仅高效,并且易用。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// 这是注释,单行注释...
|
||||||
|
/* ...这是多行注释 */
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// 1. 基础 //
|
||||||
|
///////////////
|
||||||
|
|
||||||
|
// 函数 (Functions)
|
||||||
|
// `i32` 是有符号 32 位整数类型(32-bit signed integers)
|
||||||
|
fn add2(x: i32, y: i32) -> i32 {
|
||||||
|
// 隐式返回 (不要分号)
|
||||||
|
x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主函数(Main function)
|
||||||
|
fn main() {
|
||||||
|
// 数字 (Numbers) //
|
||||||
|
|
||||||
|
// 不可变绑定
|
||||||
|
let x: i32 = 1;
|
||||||
|
|
||||||
|
// 整形/浮点型数 后缀
|
||||||
|
let y: i32 = 13i32;
|
||||||
|
let f: f64 = 1.3f64;
|
||||||
|
|
||||||
|
// 类型推导
|
||||||
|
// 大部分时间,Rust 编译器会推导变量类型,所以不必把类型显式写出来。
|
||||||
|
// 这个教程里面很多地方都显式写了类型,但是只是为了示范。
|
||||||
|
// 绝大部分时间可以交给类型推导。
|
||||||
|
let implicit_x = 1;
|
||||||
|
let implicit_f = 1.3;
|
||||||
|
|
||||||
|
// 算术运算
|
||||||
|
let sum = x + y + 13;
|
||||||
|
|
||||||
|
// 可变变量
|
||||||
|
let mut mutable = 1;
|
||||||
|
mutable = 4;
|
||||||
|
mutable += 2;
|
||||||
|
|
||||||
|
// 字符串 (Strings) //
|
||||||
|
|
||||||
|
// 字符串字面量
|
||||||
|
let x: &str = "hello world!";
|
||||||
|
|
||||||
|
// 输出
|
||||||
|
println!("{} {}", f, x); // 1.3 hello world
|
||||||
|
|
||||||
|
// 一个 `String` – 在堆上分配空间的字符串
|
||||||
|
let s: String = "hello world".to_string();
|
||||||
|
|
||||||
|
// 字符串分片(slice) - 另一个字符串的不可变视图
|
||||||
|
// 基本上就是指向一个字符串的不可变指针,它不包含字符串里任何内容,只是一个指向某个东西的指针
|
||||||
|
// 比如这里就是 `s`
|
||||||
|
let s_slice: &str = &s;
|
||||||
|
|
||||||
|
println!("{} {}", s, s_slice); // hello world hello world
|
||||||
|
|
||||||
|
// 数组 (Vectors/arrays) //
|
||||||
|
|
||||||
|
// 长度固定的数组 (array)
|
||||||
|
let four_ints: [i32; 4] = [1, 2, 3, 4];
|
||||||
|
|
||||||
|
// 变长数组 (vector)
|
||||||
|
let mut vector: Vec<i32> = vec![1, 2, 3, 4];
|
||||||
|
vector.push(5);
|
||||||
|
|
||||||
|
// 分片 - 某个数组(vector/array)的不可变视图
|
||||||
|
// 和字符串分片基本一样,只不过是针对数组的
|
||||||
|
let slice: &[i32] = &vector;
|
||||||
|
|
||||||
|
// 使用 `{:?}` 按调试样式输出
|
||||||
|
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
// 元组 (Tuples) //
|
||||||
|
|
||||||
|
// 元组是固定大小的一组值,可以是不同类型
|
||||||
|
let x: (i32, &str, f64) = (1, "hello", 3.4);
|
||||||
|
|
||||||
|
// 解构 `let`
|
||||||
|
let (a, b, c) = x;
|
||||||
|
println!("{} {} {}", a, b, c); // 1 hello 3.4
|
||||||
|
|
||||||
|
// 索引
|
||||||
|
println!("{}", x.1); // hello
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// 2. 类型 (Type) //
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
// 结构体(Sturct)
|
||||||
|
struct Point {
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let origin: Point = Point { x: 0, y: 0 };
|
||||||
|
|
||||||
|
// 匿名成员结构体,又叫“元组结构体”(‘tuple struct’)
|
||||||
|
struct Point2(i32, i32);
|
||||||
|
|
||||||
|
let origin2 = Point2(0, 0);
|
||||||
|
|
||||||
|
// 基础的 C 风格枚举类型(enum)
|
||||||
|
enum Direction {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
}
|
||||||
|
|
||||||
|
let up = Direction::Up;
|
||||||
|
|
||||||
|
// 有成员的枚举类型
|
||||||
|
enum OptionalI32 {
|
||||||
|
AnI32(i32),
|
||||||
|
Nothing,
|
||||||
|
}
|
||||||
|
|
||||||
|
let two: OptionalI32 = OptionalI32::AnI32(2);
|
||||||
|
let nothing = OptionalI32::Nothing;
|
||||||
|
|
||||||
|
// 泛型 (Generics) //
|
||||||
|
|
||||||
|
struct Foo<T> { bar: T }
|
||||||
|
|
||||||
|
// 这个在标准库里面有实现,叫 `Option`
|
||||||
|
enum Optional<T> {
|
||||||
|
SomeVal(T),
|
||||||
|
NoVal,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法 (Methods) //
|
||||||
|
|
||||||
|
impl<T> Foo<T> {
|
||||||
|
// 方法需要一个显式的 `self` 参数
|
||||||
|
fn get_bar(self) -> T {
|
||||||
|
self.bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let a_foo = Foo { bar: 1 };
|
||||||
|
println!("{}", a_foo.get_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!("it’s an i32: {}", n),
|
||||||
|
OptionalI32::Nothing => println!("it’s nothing!"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 高级模式匹配
|
||||||
|
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!("The numbers are zero!"),
|
||||||
|
FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m =>
|
||||||
|
println!("The numbers are the same"),
|
||||||
|
FooBar { x: n, y: OptionalI32::AnI32(m) } =>
|
||||||
|
println!("Different numbers: {} {}", n, m),
|
||||||
|
FooBar { x: _, y: OptionalI32::Nothing } =>
|
||||||
|
println!("The second number is Nothing!"),
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// 4. 流程控制 (Control flow) //
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
// `for` 循环
|
||||||
|
let array = [1, 2, 3];
|
||||||
|
for i in array.iter() {
|
||||||
|
println!("{}", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 区间 (Ranges)
|
||||||
|
for i in 0u32..10 {
|
||||||
|
print!("{} ", i);
|
||||||
|
}
|
||||||
|
println!("");
|
||||||
|
// 输出 `0 1 2 3 4 5 6 7 8 9 `
|
||||||
|
|
||||||
|
// `if`
|
||||||
|
if 1 == 1 {
|
||||||
|
println!("Maths is working!");
|
||||||
|
} else {
|
||||||
|
println!("Oh no...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// `if` 可以当表达式
|
||||||
|
let value = if true {
|
||||||
|
"good"
|
||||||
|
} else {
|
||||||
|
"bad"
|
||||||
|
};
|
||||||
|
|
||||||
|
// `while` 循环
|
||||||
|
while 1 == 1 {
|
||||||
|
println!("The universe is operating normally.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无限循环
|
||||||
|
loop {
|
||||||
|
println!("Hello!");
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// 5. 内存安全和指针 (Memory safety & pointers) //
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// 独占指针 (Owned pointer) - 同一时刻只能有一个对象能“拥有”这个指针
|
||||||
|
// 意味着 `Box` 离开他的作用域后,会被安全地释放
|
||||||
|
let mut mine: Box<i32> = Box::new(3);
|
||||||
|
*mine = 5; // 解引用
|
||||||
|
// `now_its_mine` 获取了 `mine` 的所有权。换句话说,`mine` 移动 (move) 了
|
||||||
|
let mut now_its_mine = mine;
|
||||||
|
*now_its_mine += 2;
|
||||||
|
|
||||||
|
println!("{}", now_its_mine); // 7
|
||||||
|
// println!("{}", mine); // 编译报错,因为现在 `now_its_mine` 独占那个指针
|
||||||
|
|
||||||
|
// 引用 (Reference) – 引用其他数据的不可变指针
|
||||||
|
// 当引用指向某个值,我们称为“借用”这个值,因为是被不可变的借用,所以不能被修改,也不能移动
|
||||||
|
// 借用一直持续到生命周期结束,即离开作用域
|
||||||
|
let mut var = 4;
|
||||||
|
var = 3;
|
||||||
|
let ref_var: &i32 = &var;
|
||||||
|
|
||||||
|
println!("{}", var); //不像 `box`, `var` 还可以继续使用
|
||||||
|
println!("{}", *ref_var);
|
||||||
|
// var = 5; // 编译报错,因为 `var` 被借用了
|
||||||
|
// *ref_var = 6; // 编译报错,因为 `ref_var` 是不可变引用
|
||||||
|
|
||||||
|
// 可变引用 (Mutable reference)
|
||||||
|
// 当一个变量被可变地借用时,也不可使用
|
||||||
|
let mut var2 = 4;
|
||||||
|
let ref_var2: &mut i32 = &mut var2;
|
||||||
|
*ref_var2 += 2;
|
||||||
|
|
||||||
|
println!("{}", *ref_var2); // 6
|
||||||
|
// var2 = 2; // 编译报错,因为 `var2` 被借用了
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 更深入的资料
|
||||||
|
|
||||||
|
Rust 还有很多很多其他内容 - 这只是 Rust 最基本的功能,帮助你了解 Rust 里面最重要的东西。
|
||||||
|
如果想深入学习 Rust,可以去读
|
||||||
|
[The Rust Programming Language](http://doc.rust-lang.org/book/index.html)
|
||||||
|
或者上 reddit [/r/rust](http://reddit.com/r/rust) 订阅。
|
||||||
|
同时 irc.mozilla.org 的 #rust 频道上的小伙伴们也非常欢迎新来的朋友。
|
||||||
|
|
||||||
|
你可以在这个在线编译器 [Rust playpen](http://play.rust-lang.org) 上尝试 Rust 的一些特性
|
||||||
|
或者上[官方网站](http://rust-lang.org).
|
Loading…
Reference in New Issue
Block a user