Треки
/
Elixir
Elixir
/
Вправи
/
Машинка на радіокеруванні
Машинка на радіокеруванні

Машинка на радіокеруванні

Навчальна вправа

Вступ

Структури

Структури - це розширення, побудоване поверх мап, яке забезпечує перевірки під час компіляції та типові значення. Структура називається так само, як модуль, у якому її визначено. Щоб визначити структуру, скористаймося конструкцією defstruct. Зазвичай ця конструкція йде відразу після визначення модуля. defstruct приймає або список атомів (для типових значень nil), або список ключових слів (для заданих типових значень). Поля без типових значень мають іти перед полями з типовими значеннями.

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

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

Доступ до полів і оновлення

Оскільки структури побудовані на мапах, ми можемо використовувати більшість функцій для мап, щоб отримувати значення та працювати з ними. Для структур Поведінка доступу не реалізована. Натомість для доступу до полів структури радимо використовувати оператор статичного доступу ..

  • отримати або вибрати значення полів:

    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]

Вказівки

У цій вправі ми пограємося з радіокерованою машинкою, на яку ми нарешті назбирали грошей.

Машинки починають із повністю зарядженою батареєю (100%). Щоразу, коли ми керуємо машинкою за допомогою пульта дистанційного керування, вона проїжджає 20 метрів і витрачає один відсоток заряду батареї. Прізвисько машинки невідоме, доки її не створять.

Радіокерована машинка має гарний світлодіодний дисплей, який показує дві частини інформації:

  • Загальну відстань, яку вона проїхала, у вигляді: "<METERS> meters".
  • Залишок заряду батареї у вигляді: "Battery at <PERCENTAGE>%".

Якщо заряд батареї сягає 0%, ми більше не можемо керувати машинкою, і дисплей батареї покаже "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, яка повертає відстань у тому вигляді, як її показано на світлодіодному дисплеї:

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

Переконайтеся, що функція приймає як аргумент лише структуру RemoteControlCar.

4. Покажіть відсоток заряду батареї

Реалізуйте функцію RemoteControlCar.display_battery/1, яка повертає відсоток заряду батареї у тому вигляді, як його показано на світлодіодному дисплеї:

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

Переконайтеся, що функція приймає як аргумент лише структуру RemoteControlCar. Якщо заряд батареї сягає 0%, на дисплеї батареї відобразиться «Battery empty».

5. Керування змінює заряд батареї та пройдену відстань

Реалізуйте функцію RemoteControlCar.drive/1, яка:

  • збільшує пройдену відстань у метрах на 20
  • витрачає 1% заряду батареї
RemoteControlCar.new("Red")
|> RemoteControlCar.drive()

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

Переконайтеся, що функція приймає як аргумент лише структуру RemoteControlCar.

6. Врахуйте керування з розрядженою батареєю

Оновіть функцію RemoteControlCar.drive/1 так, щоб вона не збільшувала пройдену відстань і не зменшувала відсоток заряду батареї, коли батарея розряджена (0%):

%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 вправ та справжнє наставництво від людей, і все це безкоштовно.