در Elixir، تاپل یک ساختار داده است که دادهها را سازماندهی میکند و تعداد ثابتی عنصر از هر نوعی را در خود نگه میدارد، اما هیچ نام مشخصی برای تکتک عناصر آن وجود ندارد. از تاپلها در Elixir اغلب برای عملیات پرمصرف از نظر خواندن حافظه استفاده میشود، چون دسترسی خواندنی به یک عنصر یک عملیات با زمان ثابت است. معمولاً وقتی که ممکن است عناصر بهصورت پویا اضافه یا حذف شوند از آنها استفاده نمیشود، چون بهجای تغییر تاپل موجود، یک تاپل تازه ساخته میشود که نیازمند تخصیص حافظه از پیش است.
در عمل، تاپلها در Elixir با آکولاد ساخته میشوند. میتوان با تابع elem/2 و با ایندکسگذاری از صفر، جداگانه به هر عنصر یک تاپل دسترسی داشت:
empty_tuple = {}
one_element_tuple = {1}
multiple_element_tuple = {1, :a, "hello"}
elem(multiple_element_tuple, 2)
# => "hello"
در عمل اغلب از تاپلها برای نمایش اطلاعات گروهبندیشده استفاده میشود.
Float.ratio(0.25)
# => {1, 4} indicating the numerator and denominator of the fraction ¼
استفاده از تطبیق الگو در کد اصیل و قطعیتگرای Elixir غالب است. شاید به یاد بیاورید که =/2 را بهجای یک عملگر انتساب، «عملگر تطبیق» میدانند. وقتی از عملگر تطبیق استفاده میکنید، اگر الگوی سمت چپ با سمت راست منطبق باشد، هر متغیری که در سمت چپ باشد مقید میشود و مقدار سمت راست بازگردانده میشود. اگر تطابقی برقرار نباشد، MatchError رخ میدهد.
2 = 2
# => 2
# Literals can be matched if they are the same
2 = 3
# => ** (MatchError) no match of right hand side value: 3
{_, denominator} = Float.ratio(0.25)
# => {1, 4}
# the variable `denominator` is bound to the value 4
به یاد داشته باشید که تطبیقها از سمت راست به سمت چپ انجام میشوند.
در مثال آخر، اگر در یک تطبیق الگو به متغیری نیاز نداشته باشیم، میتوانیم با ارجاع به _ از آن صرفنظر کنیم. هیچ متغیری که با _ شروع شود، توسط زمان اجرا ردیابی نمیشود.
تطبیق الگو ابزار مفیدی هم برای ساختن چندین بند تابع است. میتوان از تطبیق الگو روی آرگومانهای تابع استفاده کرد و همین مشخص میکند که کدام بند تابع فراخوانی شود، از بالای فایل به سمت پایین تا نخستین تطبیق. متغیرها ممکن است در سر تابع مقید شوند و در بدنهی تابع به کار روند.
defmodule Example do
def named_function(:a = variable_a) do
{variable_a, 1}
end
def named_function(:b = variable_b) do
{variable_b, 2}
end
end
Example.named_function(:a)
# => {:a, 1}
Example.named_function(:b)
# => {:b, 2}
Example.named_function(:c)
# => ** (FunctionClauseError) no function clause matching in Example.named_function/1
در حال آماده شدن برای پختن کلوچه برای دوستانتان، متوجه شدهاید که باید بعضی از اندازههای بهکاررفته در دستور پخت را تبدیل کنید. چون تنها با سیستم متریک آشنایید، باید راهی پیدا کنید تا اندازههای رایج آشپزی آمریکایی را برای راحتی خودتان به میلیلیتر (mL) تبدیل کنید.
برای حل خود از این جدول تبدیل استفاده کنید:
| واحد برای تبدیل | حجم | بر حسب میلیلیتر (mL) |
|---|---|---|
| میلیلیتر | ۱ | ۱ |
| پیمانهی آمریکایی | ۱ | ۲۴۰ |
| اونس مایع آمریکایی | ۱ | ۳۰ |
| قاشق چایخوری آمریکایی | ۱ | ۵ |
| قاشق غذاخوری آمریکایی | ۱ | ۱۵ |
چون برنامهنویسی مستعد و در حال آموزش هستید، تصمیم میگیرید میلیلیتر را به عنوان واحد واسط به کار ببرید تا تبدیل از هر واحد فهرستشده به واحد دیگر (حتی به خودش) آسانتر شود.
تابع KitchenCalculator.get_volume/1 را پیادهسازی کنید. این تابع با گرفتن یک تاپل جفت حجم، فقط جزء عددی را برمیگرداند.
KitchenCalculator.get_volume({:cup, 2.0})
# => 2.0
تابع KitchenCalculator.to_milliliter/1 را پیادهسازی کنید. این تابع با گرفتن یک تاپل جفت حجم، حجم را با استفاده از جدول تبدیل به میلیلیتر تبدیل میکند.
برای ساختن تابع هر واحد، از چند بند تابع و تطبیق الگو استفاده کنید. اتمهایی که هر واحد را نشان میدهند عبارتاند از: :cup، :fluid_ounce، :teaspoon، :tablespoon، :milliliter. نتیجهی تبدیل را داخل یک تاپل برگردانید.
KitchenCalculator.to_milliliter({:cup, 2.5})
# => {:milliliter, 600.0}
تابع KitchenCalculator.from_milliliter/2 را پیادهسازی کنید. این تابع با گرفتن یک تاپل جفت حجم و واحد دلخواه، حجم را با استفاده از جدول تبدیل به واحد دلخواه تبدیل میکند.
برای ساختن تابع هر واحد، از چند بند تابع و تطبیق الگو استفاده کنید. اتمهایی که هر واحد را نشان میدهند عبارتاند از: :cup، :fluid_ounce، :teaspoon، :tablespoon، :milliliter
KitchenCalculator.from_milliliter({:milliliter, 1320.0}, :cup)
# => {:cup, 5.5}
تابع KitchenCalculator.convert/2 را پیادهسازی کنید. این تابع با گرفتن یک تاپل جفت حجم و واحد دلخواه، حجم دادهشده را به واحد دلخواه تبدیل میکند.
KitchenCalculator.convert({:teaspoon, 9.0}, :tablespoon)
# => {:tablespoon, 3.0}