Elixir School「制御構文」の学習メモ
if/2
とunless/2
Elixirで偽とみなされる値はnil
と真偽値のfalse
だけ。
0
や''
もtrueとみなされる。
iex(70)> if true do "true" else "false" end
"true"
iex(71)> if false do "true" else "false" end
"false"
iex(72)> if nil do "true" else "false" end
"false"
iex(73)> if 1 do "true" else "false" end
"true"
iex(74)> if 0 do "true" else "false" end
"true"
iex(75)> if '' do "true" else "false" end
"true"
if〜do〜else〜endの書き方は関数の定義と同じように扱うためのシンタックスシュガーで、下記のようにも書ける。
if String.valid?("Hello"), do: "Valid string!", else: "Invalid string."
if(String.valid?("Hello"), [{:do, "Valid string!"}, {:else, "Invalid string."}])
case/2
の構文
複数のパターンに対してマッチする必要があるときに使う。
->
は他言語だとthen
にあたる。
iex(77)> case {:ok, "Hello, world"} do
...(77)> {:ok, result} -> result
...(77)> {:error} -> "Uh oh!"
...(77)> _ -> "Catch all"
...(77)> end
"Hello, world"
_
は他のすべてにマッチするelseに該当する。
マッチするものが見当たらない場合、CaseClauseError
が発生する。
iex(78)> case :even do
...(78)> :odd -> "Odd"
...(78)> end
** (CaseClauseError) no case clause matching: :even
case/2
case/2
はパターンマッチングに依存しているので、パターンマッチングと同じルールや制限がすべて適応される。
iex(78)> pie = 3.14
3.14
iex(79)> case "cherry pie" do
...(79)> ^pie -> "not so taisty"
...(79)> pie -> "i bet #{pie} is tasty"
...(79)> end
"i bet cherry pie is tasty"
iex(80)> case 3.14 do
...(80)> ^pie -> "not so taisty"
...(80)> pie -> "i bet #{pie} is tasty"
...(80)> end
"not so taisty"
case/2
はガード節に対応している。
iex(83)> case {1, 2, 3} do
...(83)> {1, x, 3} when x > 0 ->
...(83)> "will match"
...(83)> _ ->
...(83)> "won't match"
...(83)> end
"will match"
iex(84)> case {1, 0, 3} do
...(84)> {1, x, 3} when x > 0 ->
...(84)> "will match"
...(84)> _ ->
...(84)> "won't match"
...(84)> end
"won't match"
cond/1
cond/1
は他の言語でいうところのelse if
やelsif
のようなもの。
値ではなく条件をマッチさせる必要があるときに使う。
iex(86)> cond do
...(86)> 2 + 2 == 5 -> "A"
...(86)> 2 * 2 == 3 -> "B"
...(86)> 1 + 1 == 2 -> "C"
...(86)> end
"C"
case
のようにcond
はマッチしない場合にエラーを発生させる。
それに対応するにはtrue
になる条件を定義する。
iex(87)> cond do
...(87)> 7 + 1 == 0 -> "fuga"
...(87)> true -> "catch all"
...(87)> end
"catch all"
with
with式には2つの使い方がある。
まずは、ローカル変数のスコープを定義すること。計算中に一時的な変数が必要になって、その変数が外に漏れてほしくないとき。
2つ目の役割はパターンマッチングの失敗を制御したいとき。
2つ目の例
iex(90)> user = %{first: "Sean", last: "Callan"}
%{first: "Sean", last: "Callan"}
iex(92)> with {:ok, first} <- Map.fetch(user, :first),
...(92)> {:ok, last} <- Map.fetch(user, :last),
...(92)> do: last <> ", " <> first
"Callan, Sean"
with/1
はElixir1.3からelseを使える。
iex(97)> import Integer
Integer
iex(98)> m = %{a: 1, c: 3}
%{a: 1, c: 3}
iex(99)> a =
...(99)> with {:ok, number} <- Map.fetch(m, :a),
...(99)> true <- is_even(number) do
...(99)> IO.puts "#{number} divided by 2 is #{div(number, 2)}"
...(99)> :even
...(99)> else
...(99)> :error ->
...(99)> IO.puts("We don't have this item in map")
...(99)> :error
...(99)>
...(99)> _ ->
...(99)> IO.puts("It is odd")
...(99)> :odd
...(99)> end
It is odd
:odd