7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2024

Day 16

Elixirのチートシートを作ろう #10 制御構造その2

Last updated at Posted at 2024-12-15

1. OverView

さて、二日に分けた制御構造の続き。完走するなら、あと13日分かー。

2. まずは解説

2.1 cond

さて、 Elixir Schoolの解説を見てみましょう。
https://elixirschool.com/ja/lessons/basics/control_structures#cond-2

値ではなく、条件をマッチさせる必要がある時には、 cond/1 を使うことができます。これは他の言語でいうところの else if や elsif のようなものです:

まずはサンプルの実行

iex(14)> cond do
...(14)>   2 + 2 == 5 ->
...(14)>     "This will not be true"
...(14)>   2 * 2 == 3 ->
...(14)>     "Nor this"
...(14)>   1 + 1 == 2 ->
...(14)>     "But this will" <-こいつだけが実行されますね。
...(14)> end
"But this will"

iex(15)> cond do
...(15)>   7 + 1 == 0 -> "Incorrect"
...(15)>   true -> "Catch all" <-こいつが実行されております
...(15)> end
"Catch all
iex(19)> a = 1
1
iex(20)> b = 3
3
iex(21)> a + b
4
iex(22)>
nil
iex(23)> cond do
...(23)>   a + b == 2 -> "OK"
...(23)>   true -> "Catch all"
...(23)> end
"Catch all"

Else ifと言っているので、以下の様に

iex(31)> cond do
...(31)>   a + b == 2 -> "OK,2"
...(31)>   a + b == 4 -> "OK,4" -->ここがtrueになる
...(31)>   true -> "Catch all" --> ここは評価されない。
...(31)> end
"OK,4"

先頭からやって、trueになると抜けるんですね。これ。

2.2 with

2.2.1 withの説明

うん、これの為にdayを分けた。
https://elixirschool.com/ja/lessons/basics/control_structures#with-3

「特殊形式の with/1 はネストされた case/2 文を使うような時やきれいにパイプできない状況に便利です。 with/1 式はキーワード, ジェネレータ, そして式から成り立っています」

後半はわかるが…文法を調べないとさっぱりわからないな。

with
    pattern1 <- expression1,
    pattern2 <- expression2, ...,
do:
    result_expression

これ、withの後の条件が満たされた場合、「すべてが条件式を満たしたら」 do:以下のresult_expressionが実行されるらしい。

では、サンプル…理解の前にElixir Schoolの文章を読んでみましょう。

「ジェネレータについてはリスト内包表記のレッスンでより詳しく述べますが、今は <- の右側と左側を比べるのにパターンマッチが使われることを知っておくだけでよいです。」

<-の右側と左側を比べるのに、パターンマッチ、つまり、これ、関数が実行されるんですね。
なので、例は…

user = %{first: "Sean", last: "Callan"}

これとmatchする

with {:ok, first} <- Map.fetch(user, :first),
     {:ok, last} <- Map.fetch(user, :last),
     do: last <> ", " <> first

1行ずつ見ていくと、
Map.fetch(user, :first)  こいつの結果が{:ok, "Sean"}
Map.fetch(user, :last),  こいつの結果が{:ok, "Callan"}

それぞれの行がマッチするので、do:以降のresult_expressionが実行されます。

今回はresult_expressionは、以下ですね。
このサンプル、実に味があるなと思うのが、結果。

     do: last <> ", " <> first
"Callan, Sean"

結果が意味深でして。
上にも書いたとおり、「今は <- の右側と左側を比べるのにパターンマッチが使われることを知っておくだけでよいです。」の通りでして。
上の二つのパターンマッチが行われているので、last, firstに値がbindされてます。

2.2.2 with/1でelseが使えます

次のサンプル
Elixir 1.3からは with/1 で else を使えます:

import Integer
m = %{a: 1, c: 3}
a =
  with {:ok, number} <- Map.fetch(m, :a),
    true <- is_even(number)
  do
      IO.puts "#{number} divided by 2 is #{div(number, 2)}"
      :even
  else
    :error ->
      IO.puts("We don't have this item in map")
      :error
    _ ->
      IO.puts("It is odd")
      :odd
  end

実行結果が

It is odd

さて、細かく説明(と言うか、俺の理解が…)

 {:ok, number} <- Map.fetch(m, :a)  mのmapに入っているa:を取り出して、評価しております。
  is_even(number) numberが偶数か奇数か判定

これ、先ほども話した通り「今は <- の右側と左側を比べるのにパターンマッチが使われることを知っておくだけでよいです」ですね。
この両方が実行されます。
elseにて、この条件に当てはまらない

elseで二つのケースのエラーハンドリングをしています。

    :error ->
      IO.puts("We don't have this item in map")
      :error
    _ ->
      IO.puts("It is odd")
      :odd

まずは、:error。これは、Map.fetch(m, :a) が失敗した場合ですね。
次、_で、Map.fetch(m, :a)は成功したが、is_even(number)がfalseだった場合となります。

では、実行結果を張っておきます

m = %{a: 2, c: 3}
2 divided by 2 is 1
:even

m = %{q: 2, c: 3}
We don't have this item in map
:error

3. 本日のチートシート!

制御構造の名 説明
cond 値ではなく、条件をマッチさせる cond do
7 + 1 == 0 -> "Incorrect"
true -> "Catch all"
end
"Catch all"
with withで指定された複数のパターンマッチを行い、trueであればdo以下を実行する with {:ok, first} <- Map.fetch(user, :first),
{:ok, last} <- Map.fetch(user, :last),
do: last <> ", " <> first
"Callan, Sean"

4. 本日の課題.…

僕の宿題をまとめておきます。

4.1 Elixir Schoolのwithのリファクタリング例を、ちゃんと説明しよう

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?