مسیرها
/
Elixir
Elixir
/
تمرین‌ها
/
ماشین کنترل از راه دور
ماشین کنترل از راه دور

ماشین کنترل از راه دور

تمرین یادگیری

مقدمه

ساختار

«ساختارها» افزونه‌ای هستند که روی «نقشه»ها بنا شده‌اند و بررسی‌های زمان کامپایل و مقادیر پیش‌فرض را فراهم می‌کنند. هر ساختار به اسم ماژولی که در آن تعریف شده نام‌گذاری می‌شود. برای تعریف یک ساختار از سازه‌ی defstruct استفاده کنید. این سازه معمولاً بلافاصله پس از تعریف ماژول می‌آید. defstruct یا فهرستی از اتم‌ها را می‌پذیرد (برای مقادیر پیش‌فرض nil) یا یک لیست کلیدواژه (برای مقادیر پیش‌فرض مشخص‌شده). فیلدهای بدون مقدار پیش‌فرض باید پیش از فیلدهای دارای مقدار پیش‌فرض بیایند.

defmodule Plane do
  defstruct [:engine, wings: 2]
end

plane = %Plane{}
# => %Plane{engine: nil, wings: 2}

دسترسی به فیلدها و به‌روزرسانی آن‌ها

چون ساختارها روی نقشه‌ها بنا شده‌اند، می‌توانیم از بیشتر توابع نقشه برای گرفتن و دستکاری مقادیر استفاده کنیم. رفتار Access Behaviour برای ساختارها پیاده‌سازی نشده است. توصیه می‌شود برای دسترسی به فیلدهای ساختار به‌جای آن از «عملگر دسترسی ایستا» . استفاده کنید.

  • گرفتن/واکشی مقادیر فیلد:

    plane = %Plane{}
    plane.engine
    # => nil
    Map.fetch(plane, :wings)
    # => {:ok, 2}
    
  • به‌روزرسانی مقادیر فیلد

    plane = %Plane{}
    %{plane | wings: 4}
    # => %Plane{engine: nil, wings: 4}
    

تطبیق الگو

از ساختارها می‌توان در تطبیق الگو، با یا بدون اسم ساختار، استفاده کرد.

plane = %Plane{}
%Plane{wings: wings} = plane
%{wings: wings} = plane

با آوردن اسم ساختار در الگو، می‌توانید مطمئن شوید که هر دو طرف، ساختارهایی از یک نوع هستند.

defmodule Helicopter do
  defstruct [:engine, rotors: 1]
end

%Plane{} = %Helicopter{}
# => (MatchError) no match of right hand side value: %Helicopter{engine: nil, rotors: 1}

الزام به مقداردهی اولیه‌ی فیلدها

می‌توانیم از ویژگی ماژول @enforce_keys همراه با فهرستی از کلیدهای فیلد استفاده کنیم تا مطمئن شویم هنگام ساخت ساختار، مقادیر مقداردهی اولیه می‌شوند. اگر کلیدی در فهرست نباشد، مقدارش nil خواهد بود، همان‌طور که در مثال بالا دیدید. اگر کلید الزام‌شده مقداردهی اولیه نشود، خطایی ایجاد می‌شود.

defmodule User do
  @enforce_keys [:username]
  defstruct [:username]
end

%User{}
# => (ArgumentError) the following keys must also be given when building struct User: [:username]

دستورالعمل‌ها

در این تمرین با یک ماشین کنترلی بازی می‌کنید؛ همان ماشینی که بالاخره پول کافی برای خریدش را پس‌انداز کرده‌اید.

باتری ماشین‌ها در ابتدا کاملاً پر است (۱۰۰٪). هر بار که ماشین را با کنترل از راه دور می‌رانید، ۲۰ متر جلو می‌رود و یک درصد از باتری را خالی می‌کند. لقب ماشین تا وقتی که ساخته نشده باشد، مشخص نیست.

ماشین کنترلی یک نمایشگر LED شیک دارد که دو مورد اطلاعات را نشان می‌دهد:

  • مسافت کل طی‌شده، که به این شکل نمایش داده می‌شود: "<METERS> meters".
  • شارژ باقی‌مانده‌ی باتری، که به این شکل نمایش داده می‌شود: "Battery at <PERCENTAGE>%".

اگر باتری به ۰٪ برسد، دیگر نمی‌توانید ماشین را برانید و نمایشگر باتری "Battery empty" را نشان می‌دهد.

1. یک ماشین کنترلی کاملاً نو بسازید

تابع RemoteControlCar.new/0 را پیاده‌سازی کنید تا یک ساختار ماشین کنترلی کاملاً نو برگرداند:

RemoteControlCar.new()
# => %RemoteControlCar{
#      battery_percentage: 100,
#      distance_driven_in_meters: 0,
#      nickname: "none"
#    }

ساختار به لقب نیاز دارد؛ مطمئن شوید که مقدار آن در تابع new مقدار اولیه می‌گیرد، نه در خود ساختار.

2. یک ماشین کنترلی کاملاً نو با لقب بسازید

تابع RemoteControlCar.new/1 را پیاده‌سازی کنید تا یک ساختار ماشین کنترلی کاملاً نو با لقبی که داده می‌شود برگرداند:

RemoteControlCar.new("Blue")
# => %RemoteControlCar{
#      battery_percentage: 100,
#      distance_driven_in_meters: 0,
#      nickname: "Blue"
#    }

3. نمایش مسافت

تابع RemoteControlCar.display_distance/1 را پیاده‌سازی کنید تا مسافت را همان‌طور که روی نمایشگر LED نمایش داده می‌شود برگرداند:

car = RemoteControlCar.new()
RemoteControlCar.display_distance(car)
# => "0 meters"

مطمئن شوید که تابع فقط یک ساختار RemoteControlCar را به عنوان آرگومان می‌پذیرد.

4. نمایش درصد باتری

تابع RemoteControlCar.display_battery/1 را پیاده‌سازی کنید تا درصد باتری را همان‌طور که روی نمایشگر LED نمایش داده می‌شود برگرداند:

car = RemoteControlCar.new()
RemoteControlCar.display_battery(car)
# => "Battery at 100%"

مطمئن شوید که تابع فقط یک ساختار RemoteControlCar را به عنوان آرگومان می‌پذیرد. اگر باتری به ۰٪ رسیده باشد، نمایشگر باتری «Battery empty» را نشان می‌دهد.

5. رانندگی باتری و مسافت طی‌شده را تغییر می‌دهد

تابع RemoteControlCar.drive/1 را پیاده‌سازی کنید که:

  • مسافت طی‌شده را ۲۰ متر افزایش می‌دهد
  • یک درصد از باتری را خالی می‌کند
RemoteControlCar.new("Red")
|> RemoteControlCar.drive()

# => %RemoteControlCar{
#      battery_percentage: 99,
#      distance_driven_in_meters: 20,
#      nickname: "Red"
#    }

مطمئن شوید که تابع فقط یک ساختار RemoteControlCar را به عنوان آرگومان می‌پذیرد.

6. در نظر گرفتن رانندگی با باتری خالی

تابع RemoteControlCar.drive/1 را طوری تغییر دهید که وقتی باتری خالی است (۰٪)، نه مسافت طی‌شده را افزایش دهد و نه درصد باتری را کاهش دهد:

%RemoteControlCar{
  battery_percentage: 0,
  distance_driven_in_meters: 1980,
  nickname: "Red"
}
|> RemoteControlCar.drive()

# => %RemoteControlCar{
#      battery_percentage: 0,
#      distance_driven_in_meters: 1980,
#      nickname: "Red"
#    }
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Elixir Exercism

آماده‌اید ماشین کنترل از راه دور را شروع کنید؟

در Exercism ثبت‌نام کنید تا Elixir را همراه با 58 مفهوم168 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.