Μια Tuple μοιάζει αρκετά με ένα Vector (μονοδιάστατο array) από πολλές απόψεις.
Ωστόσο, υπάρχουν μερικές σημαντικές διαφορές.
( ) αντί για αγκύλες [ ], αν και οι παρενθέσεις μπορούν να παραλειφθούν σε περιπτώσεις όπου το νόημα είναι σαφές.Η αμεταβλητότητα επιτρέπει περισσότερες βελτιστοποιήσεις από τον μεταγλωττιστή και κάνει τις πλειάδες πιο αποδοτικές από τα Vector, οπότε προτιμώνται σε περιπτώσεις όπου η μεταβλητότητα δεν είναι απαραίτητη.
julia> t = (3, 5.2, "xyz")
(3, 5.2, "xyz")
# Non-homogeneous:
julia> dump(t)
Tuple{Int64, Float64, String}
1: Int64 3
2: Float64 5.2
3: String "xyz"
julia> t[2]
5.2
# Immutable:
julia> t[2] = 7.3
ERROR: MethodError: no method matching setindex!(::Tuple{Int64, Float64, String}
Υπάρχει επίσης ένας κατασκευαστής Tuple(), που μετατρέπει οποιαδήποτε επαναλήψιμη συλλογή σε πλειάδα.
Χρήσιμα, αυτό αντιμετωπίζει μια συμβολοσειρά ως επαναλήψιμη συλλογή χαρακτήρων.
julia> Tuple("Julia")
('J', 'u', 'l', 'i', 'a')
Σε οποιαδήποτε πλειάδα, μπορείς να προσπελάσεις τα στοιχεία με βάση τη θέση ή να τα διατρέξεις με έναν βρόχο.
Οποιαδήποτε καθαρά αριθμητική πλειάδα μπορεί επίσης να χρησιμοποιηθεί σε μαθηματικές συναρτήσεις όπως η sum(), ακριβώς όπως οι πίνακες.
Μια πλειάδα μπορεί να αποσυσκευαστεί σε μεμονωμένα στοιχεία χρησιμοποιώντας πολλαπλή ανάθεση.
Για στοιχεία που δεν χρειάζεσαι, χρησιμοποίησε την κάτω παύλα _ ως εικονική μεταβλητή.
julia> tup = (1, "Julia", true)
(1, "Julia", true)
julia> num, name, _ = tup
(1, "Julia", true)
julia> uppercase(name), 2num
("JULIA", 2)
Για να αντιγράψεις όλα τα στοιχεία μιας πλειάδας σε μια άλλη πλειάδα (ή γενικότερα σε μια συλλογή), υπάρχει ο τελεστής splat ... που την αποσυσκευάζει.
Αυτό θα καλυφθεί με περισσότερες λεπτομέρειες στην Έννοια Functions.
julia> new_tup = (tup..., π, '😊')
(1, "Julia", true, π, '😊')
Μια Tuple περιέχει μόνο τιμές.
Μια NamedTuple συνδυάζει κάθε τιμή με ένα όνομα.
Τα επιμέρους πεδία μπορούν στη συνέχεια να προσπελαστούν με συμβολισμό "τελείας":
julia> nt = (a = 1, b = 7.3)
(a = 1, b = 7.3)
julia> dump(nt)
@NamedTuple{a::Int64, b::Float64}
a: Int64 1
b: Float64 7.3
julia> nt.b
7.3
Το όνομα αποθηκεύεται εσωτερικά ως Symbol (ένας αμετάβλητος τύπος, και πριν από το όνομα μπαίνει η διπλή τελεία :), οπότε υπάρχει και εναλλακτική σύνταξη:
julia> nt[:b]
7.3
Μερικές φορές είναι χρήσιμο να χωρίσεις τη δημιουργία μιας ονομαστικής πλειάδας σε δύο βήματα:
# Step 1
julia> Student = NamedTuple{(:name, :grade), Tuple{String, Int}}
@NamedTuple{name::String, grade::Int64}
julia> typeof(Student)
DataType
# Step 2
julia> s = Student( ("Helen", 3) )
(name = "Helen", grade = 3)
julia> dump(s)
@NamedTuple{name::String, grade::Int64}
name: String "Helen"
grade: Int64 3
Υπάρχουν εντυπωσιακά πολλοί άλλοι τρόποι για να δημιουργήσεις μια ονομαστική πλειάδα, οπότε ρίξε μια ματιά στην τεκμηρίωση αν σε ενδιαφέρει.
Είναι εύκολο να πάρεις ξεχωριστά είτε τα ονόματα (που λέγονται και "κλειδιά") είτε τις τιμές:
julia> keys(s)
(:name, :grade)
julia> values(s)
("Helen", 3)
Σημείωσε ότι η επανάληψη πάνω σε μια ονομαστική πλειάδα παράγει μόνο τις τιμές, και τα ονόματα αγνοούνται.
Αν τα ονόματα είναι επίσης χρήσιμα σε μια επανάληψη, χρειάζονται περισσότερα βήματα.
Η NamedTuple μπορεί να μετατραπεί σε ένα Vector από Pairs (τα Pair είναι το θέμα μιας άλλης Έννοιας).
julia> pairs(s)
pairs(::NamedTuple) with 2 entries:
:name => "Helen"
:grade => 3
julia> collect(pairs(s))
2-element Vector{Pair{Symbol, Any}}:
:name => "Helen"
:grade => 3
Η ονομαστική πλειάδα μοιάζει λοιπόν αρκετά με λεξικό.
Ωστόσο, διαφέρει από ένα [Dict][dict] στη Julia με μερικούς σημαντικούς τρόπους:
Dict είναι μεταβλητό· μια NamedTuple, όπως κάθε πλειάδα, είναι αμετάβλητη.Dict είναι ευέλικτο ως προς τον τύπο των κλειδιών που δέχεται· μια NamedTuple μπορεί να χρησιμοποιήσει μόνο σύμβολα ως κλειδιά.Οι πλειάδες (ονομαστικές ή μη) είναι ένας πολύ συνηθισμένος τρόπος για να μεταφέρεις δομημένα δεδομένα προς και από συναρτήσεις. Η αμεταβλητότητα είναι καλή σε αυτή την περίπτωση χρήσης, καθώς παρέχει ασφάλεια δεδομένων και επιτρέπει πιο επιθετικές βελτιστοποιήσεις από τον μεταγλωττιστή.