Elixirの対話モードで型の仕様とビヘイビアの動作を確認してみた

# 概要
Elixirの対話モードで型の仕様とビヘイビアの動作を確認してみました。以下のページを参考にしました。

https://dev.to/gumi/elixir-20--j50

# 対話モードで実行
以下のコマンドを実行しました。

```
$ 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)> defmodule Example do
...(1)> @spec square_sum(integer, integer) :: integer
...(1)> def square_sum(first, last) do
...(1)> for i <- first..last do
...(1)> i
...(1)> end
...(1)> |> Enum.map(fn num -> num * num end)
...(1)> |> Enum.sum()
...(1)> |> round
...(1)> end
...(1)> end
{:module, Example,
 <<70, 79, 82, 49, 0, 0, 7, 36, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 252,
   0, 0, 0, 26, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:square_sum, 2}}
iex(2)> Example.square_sum(1, 4)
30
iex(3)> defmodule SerialNum do
...(3)> defstruct first: nil, last: nil
...(3)> end
{:module, SerialNum,
 <<70, 79, 82, 49, 0, 0, 6, 216, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 198,
   0, 0, 0, 19, 16, 69, 108, 105, 120, 105, 114, 46, 83, 101, 114, 105, 97, 108,
   78, 117, 109, 8, 95, 95, 105, 110, 102, ...>>,
 %SerialNum{first: nil, last: nil}}
iex(4)> defmodule Example do
...(4)> @spec square_sum(%SerialNum{first: integer, last: integer}) :: integer
...(4)> def square_sum(nums) do
...(4)> for i <- nums.first..nums.last do
...(4)> i
...(4)> end
...(4)> |> Enum.map(fn num -> num * num end)
...(4)> |> Enum.sum()
...(4)> |> round
...(4)> end
...(4)> end
warning: redefining module Example (current version defined in memory)
  iex:4

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 8, 0, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 20, 0,
   0, 0, 30, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:square_sum, 1}}
iex(5)> Example.square_sum(%SerialNum{first: 1, last: 4})
30
iex(6)> defmodule SerialNum do
...(6)> defstruct first: nil, last: nil
...(6)> @type t(first, last) :: %SerialNum{first: first, last: last}
...(6)> end
warning: redefining module SerialNum (current version defined in memory)
  iex:6

{:module, SerialNum,
 <<70, 79, 82, 49, 0, 0, 7, 72, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 198,
   0, 0, 0, 19, 16, 69, 108, 105, 120, 105, 114, 46, 83, 101, 114, 105, 97, 108,
   78, 117, 109, 8, 95, 95, 105, 110, 102, ...>>, :ok}
iex(7)> defmodule Example do
...(7)> @spec square_sum(SerialNum.t(integer, integer)) :: integer
...(7)> def square_sum(nums) do
...(7)> for i <- nums.first..nums.last do
...(7)> i
...(7)> end
...(7)> |> Enum.map(fn num -> num * num end)
...(7)> |> Enum.sum()
...(7)> |> round
...(7)> end
...(7)> end
warning: redefining module Example (current version defined in memory)
  iex:7

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 7, 236, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 20,
   0, 0, 0, 30, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:square_sum, 1}}
iex(8)> defmodule SerialNum do
...(8)> defstruct first: nil, last: nil
...(8)> @type t(first, last) :: %SerialNum{first: first, last: last}
...(8)> @type t :: %SerialNum{first: integer, last: integer}
...(8)> end
warning: redefining module SerialNum (current version defined in memory)
  iex:8

{:module, SerialNum,
 <<70, 79, 82, 49, 0, 0, 7, 116, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 198,
   0, 0, 0, 19, 16, 69, 108, 105, 120, 105, 114, 46, 83, 101, 114, 105, 97, 108,
   78, 117, 109, 8, 95, 95, 105, 110, 102, ...>>, :ok}
iex(9)> defmodule Example do
...(9)> @spec square_sum(SerialNum.t()) :: integer
...(9)> def square_sum(nums) do
...(9)> for i <- nums.first..nums.last do
...(9)> i
...(9)> end
...(9)> |> Enum.map(fn num -> num * num end)
...(9)> |> Enum.sum()
...(9)> |> round
...(9)> end
...(9)> end
warning: redefining module Example (current version defined in memory)
  iex:9

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 7, 240, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 20,
   0, 0, 0, 30, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:square_sum, 1}}
iex(10)> defmodule Parser do
...(10)> @callback parse(String.t) :: {:ok, term} | {:error, String.t}
...(10)> @callback extensions() :: [String.t]
...(10)> end
{:module, Parser,
 <<70, 79, 82, 49, 0, 0, 5, 88, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 176,
   0, 0, 0, 16, 13, 69, 108, 105, 120, 105, 114, 46, 80, 97, 114, 115, 101, 114,
   8, 95, 95, 105, 110, 102, 111, 95, 95, ...>>, :ok}
iex(11)> defmodule JSONParser do
...(11)> @behaviour Parser
...(11)> def parse(str), do: "" # ... JSONの解析処理
...(11)> def extensions, do: ["json"]
...(11)> end
warning: variable "str" is unused (if the variable is not meant to be used, prefix it with an underscore)
  iex:13: JSONParser.parse/1

{:module, JSONParser,
 <<70, 79, 82, 49, 0, 0, 5, 164, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 153,
   0, 0, 0, 15, 17, 69, 108, 105, 120, 105, 114, 46, 74, 83, 79, 78, 80, 97,
   114, 115, 101, 114, 8, 95, 95, 105, 110, ...>>, {:extensions, 0}}
iex(12)> defmodule YAMLParser do
...(12)> @behaviour Parser
...(12)> def parse(str), do: ""
...(12)> def extensions, do: ["yml"]
...(12)> end
warning: variable "str" is unused (if the variable is not meant to be used, prefix it with an underscore)
  iex:14: YAMLParser.parse/1

{:module, YAMLParser,
 <<70, 79, 82, 49, 0, 0, 5, 168, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 153,
   0, 0, 0, 15, 17, 69, 108, 105, 120, 105, 114, 46, 89, 65, 77, 76, 80, 97,
   114, 115, 101, 114, 8, 95, 95, 105, 110, ...>>, {:extensions, 0}}
iex(13)> defmodule JSONParser do
...(13)> @behaviour Parser
...(13)> def parse(str), do: ""
...(13)> end
warning: redefining module JSONParser (current version defined in memory)
  iex:13

warning: variable "str" is unused (if the variable is not meant to be used, prefix it with an underscore)
  iex:15: JSONParser.parse/1

warning: function extensions/0 required by behaviour Parser is not implemented (in module JSONParser)
  iex:13: JSONParser (module)

{:module, JSONParser,
 <<70, 79, 82, 49, 0, 0, 4, 240, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 142,
   0, 0, 0, 14, 17, 69, 108, 105, 120, 105, 114, 46, 74, 83, 79, 78, 80, 97,
   114, 115, 101, 114, 8, 95, 95, 105, 110, ...>>, {:parse, 1}}
iex(14)> defmodule Parser do
...(14)> @callback parse(String.t) :: {:ok, term} | {:error, String.t}
...(14)> @callback extensions() :: [String.t]
...(14)> def parse!(implementation, contents) do
...(14)> case implementation.parse(contents) do
...(14)> {:ok, data} -> data
...(14)> {:error, error} -> raise ArgumentError, "parsing error: #{error}"
...(14)> end
...(14)> end
...(14)> end
warning: redefining module Parser (current version defined in memory)
  iex:14

{:module, Parser,
 <<70, 79, 82, 49, 0, 0, 8, 76, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 17, 0,
   0, 0, 26, 13, 69, 108, 105, 120, 105, 114, 46, 80, 97, 114, 115, 101, 114, 8,
   95, 95, 105, 110, 102, 111, 95, 95, ...>>, {:parse!, 2}}
iex(15)> defmodule JSONParser do
...(15)> @behaviour Parser
...(15)> def parse(str), do: str
...(15)> def extensions, do: ["json"]
...(15)> end
warning: redefining module JSONParser (current version defined in memory)
  iex:15

{:module, JSONParser,
 <<70, 79, 82, 49, 0, 0, 5, 160, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 153,
   0, 0, 0, 15, 17, 69, 108, 105, 120, 105, 114, 46, 74, 83, 79, 78, 80, 97,
   114, 115, 101, 114, 8, 95, 95, 105, 110, ...>>, {:extensions, 0}}
iex(16)> Parser.parse!(JSONParser, {:ok, "データ"})
"データ"
iex(17)> 
```

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