Do you want to pick up from where you left of?
Take me there

توصیف‌ها

در الکسیر، توصیف لیست‌ها قواعد نوشتاری برای زیباسازی زبان هستند. در این درس یاد می‌گیریم چگونه از توصیف‌ها برای تکرار و تولید استفاده کنیم.

فهرست مطالب

مبانی

اغلب می‌توان از توصیف‌ها^1 برای تولید گزاره‌های^2 کوتاه برای تکرارهای Enum و Stream استفاده کرد. بیایید با نگاهی به یک توصیف ساده آغاز کنیم و سپس آن را بررسی کنیم:

iex> list = [1, 2, 3, 4, 5]
iex> for x <- list, do: x*x
[1, 4, 9, 16, 25]

اولین چیزی که متوجه می‌شویم استفاده از for و یک تولیدکننده^3 است. تولیدکننده چیست؟ تولیدکننده‌ها عبارت‌هایی^4 مانند x <- [1, 2, 3, 4] هستند که در توصیف‌های لیست یافت می‌شوند. آنها مسئول تولید مقدار بعدی هستند.

خوشبختانه، توصیف‌ها محدود به لیست نیستند؛ در واقع آنها با هر (چیز) قابل شمارشی^5 کار می‌کنند:

# Keyword Lists
iex> for {_key, val} <- [one: 1, two: 2, three: 3], do: val
[1, 2, 3]

# Maps
iex> for {k, v} <- %{"a" => "A", "b" => "B"}, do: {k, v}
[{"a", "A"}, {"b", "B"}]

# Binaries
iex> for <<c <- "hello">>, do: <<c>>
["h", "e", "l", "l", "o"]

مثل خیلی چیزهای دیگر در الکسیر، تولیدکننده‌ها از برای مقایسه‌ی ورودی با متغیر سمت چپ از تطابق الگو استفاده می کنند. اگر تطابقی یافت نشود، مقدار مربوطه نادیده گرفته می‌شود:

iex> for {:ok, val} <- [ok: "Hello", error: "Unknown", ok: "World"], do: val
["Hello", "World"]

استفاده از چندین تولیدکننده هم امکان‌پذیر است، شبیه به حلقه‌های تو در تو:

iex> list = [1, 2, 3, 4]
iex> for n <- list, times <- 1..n do
...>   String.duplicate("*", times)
...> end
["*", "*", "**", "*", "**", "***", "*", "**", "***", "****"]

برای نمایش بهتر اتفاقاتی که در حلقه می‌افتد، بیایید از IO.puts برای نمایش دو مقداری که تولید می‌شوند استفاده کنیم:

iex> for n <- list, times <- 1..n, do: IO.puts "#{n} - #{times}"
1 - 1
2 - 1
2 - 2
3 - 1
3 - 2
3 - 3
4 - 1
4 - 2
4 - 3
4 - 4

توصیف‌های لیست قواعدی برای زیباسازی زبان هستند و تنها باید هنگامی که مناسب است استفاده شوند.

پالایه‌ها

می‌توانید پالایه‌ها^6 را نوعی محافظ برای توصیف‌ها در نظر بگیرید. هنگامی که یک مقدار پالایش شده false یا nil برمی‌گرداند، از لیست نهایی کنار گذاشته می‌شود. بیایید در یک دامنه اعداد زوج را پیدا کنیم. از تابع is_even/1 ماژول Integer برای بررسی زوج بودن مقدار استفاده می‌کنیم.

import Integer
iex> for x <- 1..10, is_even(x), do: x
[2, 4, 6, 8, 10]

مثل تولیدکننده‌ها، می‌توان از چندین پالایه هم استفاده کرد. بیایید دامنه‌ی مثال پیش را گسترش دهیم و سپس مقادیر را پالایش کنیم تا تنها اعدادی که هم زوج هستند هم بر ۳ بخش‌پذیر هستند، برجا بمانند.

import Integer
iex> for x <- 1..100,
...>   is_even(x),
...>   rem(x, 3) == 0, do: x
[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]

کاربرد :into

چه می‌شود اگر بخواهیم چیزی به جز لیست تولید کنیم؟ با استفاده از گزینه‌ی :into می‌توانیم این کار را انجام دهیم! به عنوان یک قاعده‌ی کلی در نظر داشته باشید که :into هر ساختار پیاده‌سازی کننده‌ی پروتکل Collectable را می‌پذیرد.

بیایید با کمک :into یک لیست کلمات کلیدی از یک نگاشت بسازیم:

iex> for {k, v} <- [one: 1, two: 2, three: 3], into: %{}, do: {k, v}
%{one: 1, three: 3, two: 2}

از آنجا که دودویی‌ها پروتکل Collectable را پیاده‌سازی می‌کنند، می‌توانیم از توصیف لیست و :into برای ساخت رشته استفاده کنیم:

iex> for c <- [72, 101, 108, 108, 111], into: "", do: <<c>>
"Hello"

همین! توصیف لیست راهی ساده و کوتاه برای پیمایش دسته‌ها هستند.

Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!