Adding to_string simplifies Elixir code development and debugging
Let's check on an example: we write a service with airports and directions.
So far, so good. Well, we ate a cookie, we look, what's next in fat. List of the most popular destinations?

First, make a small test list and get an unreadable sheet:
Add a pinch of readability:
And we get a clear neat conclusion:
Sometimes during development you need to analyze the contents of variables. The internal representation is accurate, but not always readable. In such cases, you can teach Elixir to translate your structures into strings. To do this, define a function
As an added bonus, interpolation will automatically start working. Without an implementation
That's all. Readable code!
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}
endend
So far, so good. Well, we ate a cookie, we look, what's next in fat. List of the most popular destinations?

First, make a small test list and get an unreadable sheet:
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"}}]
Add a pinch of readability:
defimpl String.Chars, for: Airport dodefto_string(airport)do"#{airport.name} (#{airport.id})"endend
defimpl String.Chars, for: Direction dodefto_string(direction)do"#{direction.origin} → #{direction.destination}"endend
And we get a clear neat conclusion:
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)
Now seriously
Sometimes during development you need to analyze the contents of variables. The internal representation is accurate, but not always readable. In such cases, you can teach Elixir to translate your structures into strings. To do this, define a function
to_string
as part of the protocol implementation String.Chars
. As an added bonus, interpolation will automatically start working. Without an implementation
to_string
for airports, this would not work:"#{direction.origin} → #{direction.destination}"
That's all. Readable code!