[Elixir in Action]Guard clauseの優先度

control flowの章の、 [Elixir in Action]Erlang/Elixirの再帰計算におけるnon-tail recursionとtail recursion 以外のことを。

以下のように、文字列バイナリも左辺/右辺のマッチングによって分けることができます。

iex > a = "hello world"
iex > "hello " <> b = a
iex > b
"world"

以下のように、連続したマッチングもできます。

iex(5)> a = ( b = 1 + 2 )
3
iex(6)> b
3

以下のように書いた場合、パターンマッチングでは上から順にマッチングを試みます。そのため a(other) が最も先頭にきたらそれがマッチングされます。

defmodule Sample do
  def a({:sample1, b}), do: something
  def a({:sample2, c}), do: something
  def a(other), do: something
end

Elixirでは、以下のようなGuard clauseによっても適用される関数を条件付けすることができます。この時、 when で使われる型には優先度が存在します。

defmodule Sample do
  def a(x) when x < 0, do: something
  def a(0), do: something
  def a(x) when x > 0, do: something
end

優先度は以下。

number < atom < reference < fun < port < pid < tuple < map < list < bitstring(binary)

つまり、上記の Sample.a/1 に対してatomの :not_a_number を適用した場合、

  def a(x) when x > 0, do: something

が適用されます。エラーはありません。
そのため、数字だけを受け付けるようにするために以下のように書きます。

defmodule Sample do
  def a(x) when is_number and x < 0, do: something
  def a(0), do: something
  def a(x) when is_number and x > 0, do: something
end

これで、 :not_a_number のようなものは FunctionClauseError がraiseされるようになります。

Cmprehensionsは、 for x &lt;- [list], do: {何か} で構成される。 into などの要素を使ったりすると、繰り返しをより簡潔にかけたりする。なるほど。

Streamの説明もありましたが、Stream、色々できそうですね。
File.stream! でStreamにした後にごにょごにょStreamで操作した最後にto_list などでlistにして処理をする、といった例が載ってましたが、イマドキぽい感じがします 🙂

広告

[Elixir in Action]Guard clauseの優先度” への1件のフィードバック

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中