Elixirでモジュールと関数の動作を確認してみた

# 概要
Elixirでモジュールと関数の動作を確認してみました。以下のページを参考にしました。

https://dev.to/gumi/elixir-08--1c4c

# ソースから読み込ませて順次実行
以下のコマンドを実行しました。
```
$ 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)> String.length("hello")
5
iex(2)> defmodule Math do
...(2)> def sum(a, b) do
...(2)> a + b
...(2)> end
...(2)> end
{:module, Math,
 <<70, 79, 82, 49, 0, 0, 4, 220, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 136,
   0, 0, 0, 15, 11, 69, 108, 105, 120, 105, 114, 46, 77, 97, 116, 104, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 10, 97, ...>>, {:sum, 2}}
iex(3)> Math.sum(1, 2)
3
```
以下のファイルを作成しました。
```math.ex
defmodule Math do
  def sum(a, b) do
    a + b
  end
end
```
ファイルをコンパイルして実行しました。
```
$ elixirc math.ex 
$ ls
Elixir.Math.beam  math.ex
$ 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)> Math.sum(1, 2)
3
```
以下のファイルを作成しました。
```math.exs
defmodule Math do
  def sum(a, b) do
    a + b
  end
end

IO.puts Math.sum(1, 2)
```
プログラムを実行しました。
```
$ elixir math.exs
3
```
ファイルを読み込ませて対話モードで実行しました。
```
$ iex math.exs 
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

3
Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Math.sum(3, 4)
7
```
以下のファイルを作成しました。
```math.exs
defmodule Math do
  def sum(a, b) do
    do_sum(a, b)
  end

  defp do_sum(a, b) do
    a + b
  end
end

IO.puts Math.sum(1, 2)    #=> 3
IO.puts Math.do_sum(1, 2) #=> ** (UndefinedFunctionError)
```
ファイルを実行しました。
```
$ elixir math.exs 
3
** (UndefinedFunctionError) function Math.do_sum/2 is undefined or private
    Math.do_sum(1, 2)
    math.exs:12: (file)
    (elixir 1.12.2) lib/code.ex:1261: Code.require_file/2
```
以下のファイルを作成しました。
```zero.exs
defmodule Math do
  def zero?(0), do: true
  def zero?(x) when is_integer(x), do: false
end
```
ファイルを読み込ませて実行しました。
```
$ iex zero.exs 
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)> Math.zero?(0)
true
iex(2)> fun = &Math.zero?/1
&Math.zero?/1
iex(3)> is_function(fun)
true
iex(4)> fun.(0)
true
iex(5)> is_fun = &(is_function/1)
&:erlang.is_function/1
iex(6)> is_fun.(fun)
true
iex(7)> (&is_number/1).(1.0)
true
iex(8)> square = &(&1 * &1)
#Function<44.65746770/1 in :erl_eval.expr/5>
iex(9)> square.(2)
4
iex(10)> square_sum = &(square.(&1) + square.(&2))
#Function<43.65746770/2 in :erl_eval.expr/5>
iex(11)> square_sum.(3, 4)
25
iex(12)> flatten = &List.flatten(&1, &2)
&List.flatten/2
iex(13)> flatten.([1, [[2], 3]], [4, 5])
[1, 2, 3, 4, 5]
iex(14)> hypot = &:math.sqrt(square_sum.(&1, &2))
#Function<43.65746770/2 in :erl_eval.expr/5>
iex(15)> hypot.(3, 4)
5.0
iex(16)> hypot = &:math.sqrt(&1 * &1 + &2 * &2)
#Function<43.65746770/2 in :erl_eval.expr/5>
iex(17)> hypot.(3, 4)
5.0
```
以下のファイルを作成しました。
```hello.exs
defmodule DefaultTest do
  def dowork(x \\ "hello") do
    x
  end
end
```
ファイルを読み込ませて対話モードで実行しました。
```
$ iex hello.exs 
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)> DefaultTest.dowork()
"hello"
iex(2)> DefaultTest.dowork("hi")
"hi"
iex(3)> DefaultTest.dowork(1)
1
```
以下のファイルを作成しました。
```concat.exs
defmodule Concat do
  def join(a, b, sep \\ " ") do
    a <> sep <> b
  end
end
```
ファイルを読み込ませて対話モードで実行しました。
```
$ iex concat.exs 
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)> Concat.join("hello", "world")
"hello world"
iex(2)> Concat.join("hello", "world", ", ")
"hello, world"
```
以下のファイルを作成しました。
```greeter.exs
defmodule Greeter do
  def hello(name \\ nil, language \\ "en")

  def hello(name, language) when is_nil(name) do
    phrase(language) <> "world"
  end

  def hello(name, language) do
    phrase(language) <> name
  end

  defp phrase("en"), do: "hello, "
  defp phrase("ja"), do: "こんにちは"
end
```
ファイルを読み込ませて対話モードで実行しました。
```
$ iex greeter.exs 
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)> Greeter.hello()
"hello, world"
iex(2)> Greeter.hello("alice")
"hello, alice"
iex(3)> Greeter.hello("太郎", "ja")
"こんにちは太郎"
```
以下のファイルを作成しました。
```concat.exs
defmodule Concat do
  def join(a, b) do
    IO.puts "#=> join/2"
    a <> b
  end

  def join(a, b, sep \\ " ") do
    IO.puts "#=> join/3"
    a <> sep <> b
  end
end
```
ファイルを読み込ませて対話モードで実行しました。
```
$ iex concat.exs 
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

warning: this clause for join/2 cannot match because a previous clause at line 2 always matches
  concat.exs:7

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Concat.join("hello", "world")
#=> join/2
"helloworld"
iex(2)> Concat.join("hello", "world", ", ")
#=> join/3
"hello, world"
```
以下のファイルを作成しました。
```greeter.exs
defmodule Greeter do
  def hello(names, language \\ "en")

  def hello(names, language) when is_list(names) do
    hello(Enum.join(names, ", "), language)
  end

  def hello(name, language) when is_binary(name) do
    phrase(language) <> name
  end

  defp phrase("en"), do: "hello, "
  defp phrase("ja"), do: "こんにちは"
end
```
ファイルを読み込ませて対話モードで実行しました。
```
$ iex greeter.exs 
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)> Greeter.hello("alice")
"hello, alice"
iex(2)> Greeter.hello(["alice", "carroll"])
"hello, alice, carroll"
iex(3)> Greeter.hello(["桃太郎", "金太郎", "浦島太郎"], "ja")
"こんにちは桃太郎, 金太郎, 浦島太郎"
```

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