Elixir GUIDES を普通に読む2

Elixir GUIDES を読んだメモ

elixir-lang.jp

3.基本演算子

  • 文字列の連結
    • <> で連結
iex(1)> "foo" <> "bar"
"foobar"
  • 論理演算子
  • or, and, not が用意されている
    • これは true か false の論理値を期待している
    • 第一引数に論理値以外を渡すと例外が発生
iex(2)> true and true
true
iex(3)> false or is_atom(:example)
true
iex(4)> false or 1                
1
iex(5)> 1 or false
** (BadBooleanError) expected a boolean on left-side of "or", got: 1
  • どの型の引数でも受け取れる||, &&, ! もある

    • false と nil 以外を true として評価する
  • 比較演算子

    • ==, !=, ===, !==, <=, >=, <, > がある
    • ===== の違いは === の方がより厳格
iex(5)> 1 == 1.0
true
iex(6)> 1 === 1.0
false
  • Elixir は二つの異なる型も比較できる
iex(7)> 1 < :atom
true
number < atom < reference < function < port < pid < tuple < map < list < bitstring

4.パターン・マッチング

マッチ演算子

iex(1)> x = 1
1
iex(2)> x
1
iex(3)> 1 = x 
1
iex(4)> 2 = x
** (MatchError) no match of right hand side value: 1
    (stdlib) erl_eval.erl:453: :erl_eval.expr/5
    (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:27: IEx.Evaluator.init/4
  • = は変数が左辺にある時のみ代入される
  • 1 = x はパターンマッチ

  • タプルでパターンマッチも扱える

iex(4)> {a, b, c} = {:hello, "world", 42}
{:hello, "world", 42}
iex(5)> c
42
iex(6)> a
:hello
iex(7)> b
"world"
  • 変数のタプルをマッチさせることで解体して扱うことができる
  • タプルのサイズが違ったり、リストをマッチさせようとするとエラーとなる

  • 値を指定してのパターンマッチもできる

iex(8)> {:ok, result} = {:ok, 13}
{:ok, 13}
iex(9)> result
13
iex(10)> {:ok, result} = {:error, :oops}
** (MatchError) no match of right hand side value: {:error, :oops}
    (stdlib) erl_eval.erl:453: :erl_eval.expr/5
    (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:27: IEx.Evaluator.init/4
iex(10)> {:error, result} = {:error, :oops}
{:error, :oops}
iex(11)> result
:oops
  • リストのパターンマッチもできる
iex(12)> [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex(13)> a
1
  • リストの head と tail を取ることもできる
iex(19)> [head | tail] = [1, 2, 3] 
[1, 2, 3]
iex(20)> head                      
1
iex(21)> tail                     
[2, 3]
  • [head | tail] この形式は、リストに値を追加するときにも使える
iex(22)> list = [1, 2, 3]
[1, 2, 3]
iex(23)> [0 | list]
[0, 1, 2, 3]
  • elixir は再代入できる
  • 変数のパターンマッチを行いたいときはピン演算子を用いる
iex(27)> x = 1 
1
iex(28)> ^x = 2
** (MatchError) no match of right hand side value: 2
    (stdlib) erl_eval.erl:453: :erl_eval.expr/5
    (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:27: IEx.Evaluator.init/4
iex(28)> ^x = 1
1

5.case, cond, そして if

case

  • パターンのいずれかにマッチするまで処理を行う
  • マッチしないときはエラーを返す
iex(29)> case {1, 2, 3} do
...(29)>   {4, 5, 6} ->
...(29)>     "This clause won't match"
...(29)>   {1, x, 3} ->
...(29)>     "This clause will match and bind x to 2 in this clause"
...(29)>   _ ->
...(29)>     "This clause would match any value"
...(29)> end
"This clause will match and bind x to 2 in this clause"
  • ガードを使って条件を指定することもできる
iex(31)> case {1, 2, 3} do
...(31)>   {1, x, 3} when x > 0 ->
...(31)>     "Will match"
...(31)>   _ ->
...(31)>     "Would match, if guard condition were not satisfied"
...(31)> end
"Will match"

cond

  • else if に相当する
iex(32)> cond do
...(32)>   2 + 2 == 5 ->
...(32)>     "This will not be true"
...(32)>   2 * 2 == 3 ->
...(32)>     "Nor this"
...(32)>   1 + 1 == 2 ->
...(32)>     "But this will"
...(32)> end
"But this will"
  • nilfalse 以外の値は true となる

if と unless

  • ひとつの条件だけを検証したい時に用いる
  • falsenil が条件の時はnilを返す
    • unless では逆になる
iex(33)> if true do
...(33)>   "This works!"
...(33)> end
"This works!"
iex(34)> if nil do
...(34)>   "This won't be seen"
...(34)> end                 
nil

do/end ブロック

  • do/end はこのようにも書ける
iex(35)> if true, do: 1 + 2 
3
  • これはキーワードリストを使っているためこういう使い方もできる
iex(36)> if false, do: :this, else: :that
:that