Elixir basics · Lesson 21 (open contents)
01 · Let the code speak02 · Meet six kinds of values03 · Put values together04 · Build a new list05 · Make the shapes match06 · Choose with case07 · Parse a number safely08 · Unpack &1 and the pipe09 · Put code in a project10 · Ask precise true-or-false questions11 · Read and update nested data12 · Count visible text and bytes13 · Let function clauses choose14 · Solve a list twice15 · Choose the smallest clear control form16 · Give domain data a shape17 · Put one tested module in Mix18 · Make success and failure predictable19 · Read and write one real file20 · Take only the data you need21 · Give different data one shared action22 · Write a callback contract23 · Write down the data contract24 · Test behavior and boundaries25 · Turn a project into a command26 · Write the project promise27 · Parse one real line28 · Keep the public API small29 · Make the promise executable30 · Package the edge and leave clues31 · Prove the project is done
ELIXIR · INTERMEDIATE · LESSON 2125 minutes

Give different data one shared action

Define a protocol and implement it for two data types.

01 · Start with the whole example

Run this first

Run it once, change one input, and compare the new result.

Elixir
# Give integers and lists one shared rendering API
defprotocol Readable do
  def render(value)
end
defimpl Readable, for: Integer do
  def render(value), do: "number=#{value}"
end
defimpl Readable, for: List do
  def render(value), do: "items=#{length(value)}"
end

{Readable.render(7), Readable.render([:a, :b])}
Check the result first
  • The result is {"number=7", "items=2"}.
02 · Take the code apart

Read from the first line down

  1. Read defprotocol: Declare a shared operation.
  2. Read defimpl ... for:: Implement that operation for one type.
  3. Read to_string/1: Convert a value through the String.Chars protocol.
03 · Meet the new symbols

Symbols are not secret signs

defprotocol

Declare a shared operation.

defimpl ... for:

Implement that operation for one type.

to_string/1

Convert a value through the String.Chars protocol.

04 · Ideas inside the code

Match each name to its meaning

01

protocol

A protocol chooses an implementation from the type of its first argument.

02

implementation

defimpl supplies protocol behavior for one data type.

03

dispatch

Protocol dispatch selects the matching implementation at runtime.

05 · Make the idea clear

Why these forms are useful

Run the example first. Predict one result, then change one input and run it again.

A protocol chooses an implementation from the type of its first argument.

defimpl supplies protocol behavior for one data type.

06 · Change it yourself

Close the answer and try

Add a protocol implementation for Atom.

Practice starting point
defimpl Readable, for: ____ do
  def render(value), do: "atom=#{____}"
end

Target result: Readable.render(:ok) should return "atom=ok".

Stuck? Read one hint

Use Atom and Atom.to_string(value).

After you run it, see one answer
One answer
defimpl Readable, for: Atom do
  def render(value), do: "atom=#{Atom.to_string(value)}"
end
Think about it: Does a protocol dispatch on every argument?

No. Elixir protocols dispatch on the type of the first argument.

Take with you

Remember these three lines

  1. 1

    Protocols provide one action across types.

  2. 2

    Each type owns an implementation.

  3. 3

    Use protocols for data-type polymorphism, not process behavior.

Lesson completeRun the code once, then mark this lesson as done.