Проверим на примере: пишем сервис с аэропортами и направлениями.
defmodule Airport do
defstruct [:id, :name]
end
defmodule Direction do
defstruct [:origin, :destination]
def example do
madrid = %Airport{id: "MAD", name: "Madrid"}
riga = %Airport{id: "RIX", name: "Riga"}
%Direction{origin: riga, destination: madrid}
end
end
Пока что всё в порядке. Отлично, съели печеньку, смотрим, что дальше в джире. Список самых популярных направлений?
Для начала делаем небольшой тестовый список и получаем нечитаемую простыню:
popular = Enum.map(1..5, fn _ -> Direction.example end)
# =>
# [%Direction{destination: %Airport{id: "MAD", name: "Madrid"},
# origin: %Airport{id: "RIX", name: "Riga"}},
# %Direction{destination: %Airport{id: "MAD", name: "Madrid"},
# origin: %Airport{id: "RIX", name: "Riga"}},
# %Direction{destination: %Airport{id: "MAD", name: "Madrid"},
# origin: %Airport{id: "RIX", name: "Riga"}},
# %Direction{destination: %Airport{id: "MAD", name: "Madrid"},
# origin: %Airport{id: "RIX", name: "Riga"}},
# %Direction{destination: %Airport{id: "MAD", name: "Madrid"},
# origin: %Airport{id: "RIX", name: "Riga"}}]
Добавляем щепотку читаемости:
defimpl String.Chars, for: Airport do
def to_string(airport) do
"#{airport.name} (#{airport.id})"
end
end
defimpl String.Chars, for: Direction do
def to_string(direction) do
"#{direction.origin} → #{direction.destination}"
end
end
И получаем понятный аккуратный вывод:
Enum.each(popular, fn(x) -> IO.puts(x) end)
# =>
# Riga (RIX) → Madrid (MAD)
# Riga (RIX) → Madrid (MAD)
# Riga (RIX) → Madrid (MAD)
# Riga (RIX) → Madrid (MAD)
# Riga (RIX) → Madrid (MAD)
А теперь серьёзно
Иногда при разработке нужно анализировать содержимое переменных. Внутреннее представление точное, но не всегда читаемое. В таких случаях можно научить Elixir переводить ваши структуры в строки. Для этого определите функцию to_string
в рамках реализации протокола String.Chars
.
В качестве дополнительного бонуса автоматом начнёт работать интерполяция. Без реализации to_string
для аэропортов такое бы не сработало:
"#{direction.origin} → #{direction.destination}"
На этом всё. Читаемого кода!
Автор: HedgeSky