もやもやエンジニア

IT系のネタで思ったことや技術系のネタを備忘録的に綴っていきます。フロント率高め。

Elixir 入門 その7 - Modules

Compilation

  • defmodule マクロでモジュールを定義できる
  • defmodule内のdefでメソッドを定義できる
defmodule Math do
  def sum(a, b) do
    a + b
  end
end
> elixirc math.ex
  • コンパイルすると Elixir.Math.beam という名前のファイルが生成される。
  • iex起動時にカレントにbeamファイルがあると自動的に読み込まれる

Scripted mode

  • .exではなく.exsで保存するとscriptモードで実行できる
defmodule Math do
  def sum(a, b) do
    a + b
  end
end

IO.puts Math.sum(1, 2)
> elixir math.exs
3

Named functions

  • defpを使うと モジュール内からのみ参照できるprivate functionを定義できる
  • functionの宣言はguardをサポートしている
  • functionの宣言は同じ名前の宣言も許容される。Elixirは与えられた値がマッチする関数を探し、ない場合は例外を投げる
defmodule Math do

  def is_zero(0) do
    true
  end

  def is_zero(x) when is_number(x) do
    false
  end

end
# is_zero(0)にマッチ
> Math.is_zero(0)
true

# まず is_zero(x)にマッチして、次にis_number(x)のガードを通るので is_zero(x) when is_number(x) にマッチ
> Math.is_zero(1)
false

# 上と同じだけどis_number(x)のガードを通らないのでマッチするパターンがなく例外が投げられる
> Math.is_zero("1")
** (FunctionClauseError) no function clause matching in Math.is_zero/1
    math.ex:11: Math.is_zero("1")
  • 探索順は定義されている順になるので注意。上記の場合、is_zero(0)をis_zero(x) の下に移動した場合、0を与えても常にis_zero(x)に先にマッチしてしまう。

Function capturing

  • 関数はvaliableに束縛できる
  • &をつけて関数名/アーティを指定
iex> fun = &Math.is_zero/1
&Math.is_zero/1

iex>fun.(0)
true
  • 無名関数を作るときにも使える
  • 関数内の引数は&1, &2 のような形で使える
iex> fun1 = fn x -> x + 1 end
iex> fun1.(1)
2

iex> fun2 = &(&1 + 1)
iex> fun2.(1)
2

Default arguments

  • 名前付き関数は引数のデフォルト値を設置できる
defmodule Math do

  def sum_(a, b \\ 1) do
      a + b
  end

end
# 引数が指定されない場合は1がデフォルトで設定
iex> Math.sum_(1)
2

# 引数が指定された場合をその値を使用
iex> Math.sum_(1, 3)
4