Adding to_string simplifies Elixir code development and debugging

    Let's check on an example: we write a service with airports and directions.

    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_stringas part of the protocol implementation String.Chars.

    As an added bonus, interpolation will automatically start working. Without an implementation to_stringfor airports, this would not work:

    "#{direction.origin}#{direction.destination}"

    That's all. Readable code!

    Also popular now: