LoginSignup
15
0

More than 1 year has passed since last update.

今日のElixirSchoolメモ5「制御構文」

Posted at

Elixir School「制御構文」の学習メモ

if/2unless/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 ifelsifのようなもの。
値ではなく条件をマッチさせる必要があるときに使う。

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
15
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
0