یک 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)
برنامهنویسان پایتون با این نحوهی نگارش تخصیص چندگانه کاملاً آشنا خواهند بود.
یک 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
بهآسانی میتوان اسمها (که به آنها «کلید» هم میگویند) یا مقدارها را جداگانه به دست آورد:
julia> nt
(a = 1, b = 7.3)
julia> keys(nt)
(:a, :b)
julia> values(nt)
(1, 7.3)
توجه داشته باشید که پیمایش روی یک تاپل نامدار فقط مقدارها را تولید میکند و اسمها نادیده گرفته میشوند.
تاپلها (چه نامدار و چه بینام) روشی بسیار رایج برای فرستادن دادههای ساختیافته به توابع و گرفتن آنها از توابع هستند. تغییرناپذیری در این کاربرد خوب است، چون ایمنی داده را تضمین میکند و به کامپایلر اجازه میدهد بهینهسازیهای قویتری انجام دهد.
آزارا و روی همتیمیاند و در یک شکار گنج با حالوهوای دزدان دریایی با هم رقابت میکنند. یکی فهرستی از گنجها همراه با مختصات نقشه دارد و دیگری فهرستی از نام مکانها همراه با مختصات نقشه. نقشههای خالیای هم به آنها داده شده که محل شروع رویشان با عبارت «شما اینجا هستید» مشخص شده است.
| فهرست آزارا | فهرست روی | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
اما اوضاع کمی نامرتب است: به نظر میرسد مختصات آزارا قالببندی و مرتبسازی متفاوتی از مختصات روی دارد و باید مدام از یک فهرست به فهرست دیگر نگاه کنند تا بفهمند کدام گنجها به کدام مکانها مربوطاند. آزارا و روی که برنامهنویسان تازهکار Julia هستند، پیش شما آمدهاند تا در نوشتن یک برنامهی کوچک (در واقع مجموعهای از توابع) برای سامان دادن بهتر به اطلاعات شکارشان کمکشان کنید.
تابع get_cooordinate() را پیادهسازی کنید که یک جفت (treasure, coordinate) از فهرست آزارا میگیرد و فقط مختصات نقشهی استخراجشده را برمیگرداند.
julia> get_cooordinate( ("Scrimshaw Whale's Tooth", "2A") )
"2A"
تابع convert_coordinate() را پیادهسازی کنید که مختصاتی در قالب «2A» میگیرد و یک تاپل در قالب ('2', 'A') برمیگرداند.
julia> convert_coordinate("2A")
('2', 'A')
تابع compare_records() را پیادهسازی کنید که یک جفت (treasure, coordinate) و یک رکورد (location, coordinate, quadrant) میگیرد و مختصات هر دو را با هم مقایسه میکند.
اگر مختصات «تطبیق» داشته باشند، true را برگردانید و اگر نداشته باشند، false را.
برای مقایسهی دقیق، مختصات را در صورت نیاز دوباره قالببندی کنید.
julia> compare_records(("Brass Spyglass", "4B"), ("Seaside Cottages", ('1', 'C'), "blue"))
false
julia> compare_records(("Model Ship in Large Bottle", "8A"), ("Harbor Managers Office", ('8', 'A'), "purple"))
true
تابع create_record() را پیادهسازی کنید که یک جفت (treasure, coordinate) از فهرست آزارا و یک رکورد (location, coordinate, quadrant) از فهرست روی میگیرد و اگر مختصات تطبیق داشته باشند، (coordinate, location, quadrant, treasure) را برمیگرداند.
اگر مختصات تطبیق نداشته باشند، یک تاپل خالی برگردانید. برای مقایسهی دقیق، مختصات را در صورت نیاز دوباره قالببندی کنید.
julia> create_record(("Brass Spyglass", "4B"), ("Abandoned Lighthouse", ('4', 'B'), "Blue"))
("4B", "Abandoned Lighthouse", "Blue", "Brass Spyglass")
julia> create_record(("Brass Spyglass", "4B"), ("Seaside Cottages", ('1', 'C'), "Blue"))
()