مپها در Elixir ساختار دادهای برای ذخیرهی اطلاعات در قالب جفتهای کلید-مقدار هستند. در زبانهای دیگر، این ساختار ممکن است با نامهایی مثل آرایههای انجمنی (PHP)، هشها (Perl 5، Raku) یا دیکشنریها (Python) شناخته شود.
کلیدها و مقدارها میتوانند از هر نوع دادهای باشند، اما اگر کلید یک اتم باشد میتوانیم آن را به شکل کوتاهتری بنویسیم. مپها ترتیب ورودیهایشان را هنگام دسترسی یا بازگرداندن تضمین نمیکنند.
یک مپ خالی بهسادگی با %{} تعریف میشود. اگر بخواهیم عنصری به یک مپ لیترال اضافه کنیم، میتوانیم از دو شکل استفاده کنیم:
# If the key is an atom:
%{atom_key: 1}
# If the key is a different type:
%{1 => :atom_value}
# You can even mix these if the atom form comes second:
%{"first_form" => :a, atom_form: :b}
هرچند قالب استاندارد و یگانهای وجود ندارد، روشی یکدست برای نمایش جفتهای کلید-مقدار انتخاب کنید.
Elixir توابع زیادی برای کار با مپها در ماژول Map ارائه میدهد. بعضی از توابع ماژول Map نیاز دارند یک تابع بینام به آنها داده شود تا به تبدیل مپ کمک کند.
در Elixir میتوانیم ویژگیهای ماژول را تعریف کنیم که میتوانند بهعنوان ثابت در توابعمان استفاده شوند.
defmodule Example do
# Defines the attribute as the value 1
@constant_number 1
def example_value() do
# Returns the value 1
@constant_number
end
end
وقتی ویژگیها برای تعریف ثابتهای ماژول به کار میروند، میتوانند هر عبارتی باشند که در زمان کامپایل ارزیابی میشود. پس از کامپایل، ویژگیهای ماژول قابل دسترسی نیستند، چون در هنگام کامپایل بسط داده میشوند؛ درست مثل ماکروهای تعریفشده در زبانهایی مانند C.
در این تمرین، روشی را پیادهسازی میکنید که با آن امتیازهای برتر محبوبترین بازی سالن آرکید محلهتان را پیگیری کنید.
برای ساختن یک نقشهی تازه از امتیازهای برتر، تابع HighScore.new/0 را تعریف کنید که هیچ آرگومانی نمیگیرد و یک نقشهی تازه و خالی از امتیازهای برتر برمیگرداند.
HighScore.new()
# => %{}
برای افزودن یک بازیکن به نقشهی امتیازهای برتر، تابع HighScore.add_player/3 را تعریف کنید؛ این تابع ۳ آرگومان میگیرد:
امتیاز اولیهی پیشفرض را در یک ویژگی ماژول ذخیره کنید. بعداً دوباره به آن نیاز پیدا خواهید کرد.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas")
# => %{"Dave Thomas" => 0}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"Dave Thomas" => 0, "José Valim"=> 486_373}
برای حذف یک بازیکن از نقشهی امتیازهای برتر، تابع HighScore.remove_player/2 را تعریف کنید؛ این تابع ۲ آرگومان میگیرد:
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas")
# => %{"Dave Thomas" => 0}
score_map = HighScore.remove_player(score_map, "Dave Thomas")
# => %{}
برای بازنشانی امتیاز یک بازیکن، تابع HighScore.reset_score/2 را تعریف کنید؛ این تابع ۲ آرگومان میگیرد:
تابع باید در حالتی هم کار کند که بازیکن امتیازی نداشته باشد.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"José Valim"=> 486_373}
score_map = HighScore.reset_score(score_map, "José Valim")
# => %{"José Valim"=> 0}
برای بهروزرسانی امتیاز یک بازیکن با افزودن به امتیاز قبلی، تابع HighScore.update_score/3 را تعریف کنید؛ این تابع ۳ آرگومان میگیرد:
تابع باید در حالتی هم کار کند که بازیکن امتیاز قبلی نداشته باشد؛ فرض کنید امتیاز قبلی ۰ است.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"José Valim"=> 486_373}
score_map = HighScore.update_score(score_map, "José Valim", 5)
# => %{"José Valim"=> 486_378}
برای گرفتن فهرست بازیکنها، تابع HighScore.get_players/1 را تعریف کنید؛ این تابع ۱ آرگومان میگیرد:
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas", 2_374)
# => %{"Dave Thomas" => 2_374}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"Dave Thomas" => 2_374, "José Valim"=> 486_373}
HighScore.get_players(score_map)
# => ["Dave Thomas", "José Valim"]