Elixirの対話モードでプロトコルの動作を確認してみた

# 概要
Elixirの対話モードでプロトコルの動作を確認してみました。以下のページを参考にしました。

https://dev.to/gumi/elixir-16--lif

# 対話モードで実行
以下のコマンドを実行しました。
```
$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> to_string(1)
"1"
iex(2)> to_string(:atom)
"atom"
iex(3)> to_string({3.14, "apple", :pie})
** (Protocol.UndefinedError) protocol String.Chars not implemented for {3.14, "apple", :pie} of type Tuple
    (elixir 1.12.2) lib/string/chars.ex:3: String.Chars.impl_for!/1
    (elixir 1.12.2) lib/string/chars.ex:22: String.Chars.to_string/1
iex(3)> defimpl String.Chars, for: Tuple do
...(3)> def to_string(tuple) do
...(3)> interior =
...(3)> tuple
...(3)> |> Tuple.to_list()
...(3)> |> Enum.map(&Kernel.to_string/1)
...(3)> |> Enum.join(", ")
...(3)> "{#{interior}}"
...(3)> end
...(3)> end
{:module, String.Chars.Tuple,
 <<70, 79, 82, 49, 0, 0, 9, 20, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 29, 0,
   0, 0, 27, 25, 69, 108, 105, 120, 105, 114, 46, 83, 116, 114, 105, 110, 103,
   46, 67, 104, 97, 114, 115, 46, 84, 117, ...>>, {:__impl__, 1}}
iex(4)> to_string({3.14, "apple", :pie})
"{3.14, apple, pie}"
iex(5)> defprotocol Size do
...(5)> @doc "データ構造のサイズを求めます。"
...(5)> def size(data)
...(5)> end
{:module, Size,
 <<70, 79, 82, 49, 0, 0, 18, 212, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 2, 114,
   0, 0, 0, 50, 11, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 10, 97, ...>>, {:__protocol__, 1}}
iex(6)> defimpl Size, for: BitString do
...(6)> def size(string), do: byte_size(string)
...(6)> end
{:module, Size.BitString,
 <<70, 79, 82, 49, 0, 0, 6, 220, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 213,
   0, 0, 0, 21, 21, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 46, 66,
   105, 116, 83, 116, 114, 105, 110, 103, 8, ...>>, {:__impl__, 1}}
iex(7)> defimpl Size, for: Map do
...(7)> def size(map), do: map_size(map)
...(7)> end
{:module, Size.Map,
 <<70, 79, 82, 49, 0, 0, 6, 192, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 200,
   0, 0, 0, 21, 15, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 46, 77,
   97, 112, 8, 95, 95, 105, 110, 102, 111, ...>>, {:__impl__, 1}}
iex(8)> defimpl Size, for: Tuple do
...(8)> def size(tuple), do: tuple_size(tuple)
...(8)> end
{:module, Size.Tuple,
 <<70, 79, 82, 49, 0, 0, 6, 200, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 206,
   0, 0, 0, 21, 17, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 46, 84,
   117, 112, 108, 101, 8, 95, 95, 105, 110, ...>>, {:__impl__, 1}}
iex(9)> Size.size("hello")
5
iex(10)> Size.size({:hello, "world"})
2
iex(11)> Size.size(%{hello: "world"})
1
iex(12)> Size.size([:hello, "world"])
** (Protocol.UndefinedError) protocol Size not implemented for [:hello, "world"] of type List
    iex:5: Size.impl_for!/1
    iex:7: Size.size/1
iex(12)> Size.size(%{})
0
iex(13)> set = %MapSet{} = MapSet.new
#MapSet<[]>
iex(14)> Size.size(set)
** (Protocol.UndefinedError) protocol Size not implemented for #MapSet<[]> of type MapSet (a struct)
    iex:5: Size.impl_for!/1
    iex:7: Size.size/1
iex(14)> MapSet.size(set)
0
iex(15)> defimpl Size, for: MapSet do
...(15)> def size(set), do: MapSet.size(set)
...(15)> end
{:module, Size.MapSet,
 <<70, 79, 82, 49, 0, 0, 6, 188, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 197,
   0, 0, 0, 20, 18, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 46, 77,
   97, 112, 83, 101, 116, 8, 95, 95, 105, ...>>, {:__impl__, 1}}
iex(16)> Size.size(%MapSet{})
0
iex(17)> defmodule User do
...(17)> defstruct [:name, :age]
...(17)> end
{:module, User,
 <<70, 79, 82, 49, 0, 0, 6, 192, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 193,
   0, 0, 0, 19, 11, 69, 108, 105, 120, 105, 114, 46, 85, 115, 101, 114, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 10, 97, ...>>, %User{age: nil, name: nil}}
iex(18)> defimpl Size, for: User do
...(18)> def size(_user), do: 2
...(18)> end
{:module, Size.User,
 <<70, 79, 82, 49, 0, 0, 6, 160, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 193,
   0, 0, 0, 20, 16, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 46, 85,
   115, 101, 114, 8, 95, 95, 105, 110, 102, ...>>, {:__impl__, 1}}
iex(19)> john = %User{age: 27, name: "John"}
%User{age: 27, name: "John"}
iex(20)> Size.size(john)
2
iex(21)> defimpl Size, for: Any do
...(21)> def size(_), do: 0
...(21)> end
{:module, Size.Any,
 <<70, 79, 82, 49, 0, 0, 6, 144, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 191,
   0, 0, 0, 20, 15, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 46, 65,
   110, 121, 8, 95, 95, 105, 110, 102, 111, ...>>, {:__impl__, 1}}
iex(22)> defmodule OtherUser do
...(22)> @derive [Size]
...(22)> defstruct [:name, :age]
...(22)> end
{:module, OtherUser,
 <<70, 79, 82, 49, 0, 0, 6, 220, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 198,
   0, 0, 0, 19, 16, 69, 108, 105, 120, 105, 114, 46, 79, 116, 104, 101, 114, 85,
   115, 101, 114, 8, 95, 95, 105, 110, 102, ...>>,
 %OtherUser{age: nil, name: nil}}
iex(23)> Size.size(%OtherUser{})
0
iex(24)> Size.size([1, 2, 3])
** (Protocol.UndefinedError) protocol Size not implemented for [1, 2, 3] of type List
    iex:5: Size.impl_for!/1
    iex:7: Size.size/1
iex(24)> defprotocol Size do
...(24)> @fallback_to_any true
...(24)> def size(data)
...(24)> end
warning: redefining module Size (current version defined in memory)
  iex:24

{:module, Size,
 <<70, 79, 82, 49, 0, 0, 18, 20, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 2, 79,
   0, 0, 0, 47, 11, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 10, 97, ...>>, {:__protocol__, 1}}
iex(25)> defimpl Size, for: Any do
...(25)> def size(_), do: 0
...(25)> end
warning: redefining module Size.Any (current version defined in memory)
  iex:25

{:module, Size.Any,
 <<70, 79, 82, 49, 0, 0, 6, 144, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 191,
   0, 0, 0, 20, 15, 69, 108, 105, 120, 105, 114, 46, 83, 105, 122, 101, 46, 65,
   110, 121, 8, 95, 95, 105, 110, 102, 111, ...>>, {:__impl__, 1}}
iex(26)> Size.size([1, 2, 3])
0
iex(27)> Enum.map([1, 2, 3], fn(x) -> x * x end)
[1, 4, 9]
iex(28)> Enum.reduce([1, 2, 3], 0, fn(x, acc) -> x + acc end)
6
iex(29)> to_string(:hello)
"hello"
iex(30)> age = 25
25
iex(31)> "age: #{age}"
"age: 25"
iex(32)> tuple = {1, 2, 3}
{1, 2, 3}
iex(33)> "tuple: #{tuple}"
"tuple: {1, 2, 3}"
iex(34)> "tuple: #{inspect(tuple)}"
"tuple: {1, 2, 3}"
iex(35)> {1, 2, 3}
{1, 2, 3}
iex(36)> %User{name: "john", age: 27}
%User{age: 27, name: "john"}
iex(37)> inspect &(&1+2)
"#Function<44.65746770/1 in :erl_eval.expr/5>"
iex(38)> 
```

# まとめ
何かの役に立てばと。