एक Tuple कई मामलों में Vector (एक-आयामी array) से काफी मिलता-जुलता है। फिर भी, कुछ ज़रूरी अंतर हैं।
[ ] के बजाय गोल ब्रैकेट ( ) में लिखे जाते हैं, हालाँकि जहाँ अर्थ स्पष्ट हो, वहाँ गोल ब्रैकेट छोड़े भी जा सकते हैं।इम्यूटेबिलिटी से कंपाइलर को ज़्यादा ऑप्टिमाइज़ेशन करने का मौका मिलता है और ट्यूपल वेक्टर की तुलना में ज़्यादा तेज़ होते हैं। इसलिए जहाँ बदलाव की ज़रूरत न हो, वहाँ ट्यूपल का इस्तेमाल करना चाहिए।
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 ऑपरेटर है, जो उसे अनपैक करता है। इसके बारे में फंक्शन कॉन्सेप्ट में और विस्तार से बताया जाएगा।
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 को Pairs के Vector में बदला जा सकता है (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
इस तरह नेम्ड ट्यूपल डिक्शनरी जैसा ही होता है।
फिर भी, Julia में यह [Dict][dict] से कुछ ज़रूरी मामलों में अलग है:
Dict म्यूटेबल होता है, जबकि NamedTuple किसी भी ट्यूपल की तरह इम्यूटेबल होता है।Dict की के टाइप को लेकर लचीला होता है; NamedTuple की के तौर पर सिर्फ सिंबल इस्तेमाल कर सकता है।ट्यूपल (नेम्ड हों या न हों) फंक्शन तक और फंक्शन से संरचित डेटा भेजने का बहुत आम तरीका हैं। इस इस्तेमाल में इम्यूटेबिलिटी फायदेमंद है, क्योंकि यह डेटा की सुरक्षा देती है और कंपाइलर को ज़्यादा आक्रामक ऑप्टिमाइज़ेशन का मौका देती है।