Elixir GUIDES を普通に読む2
Elixir GUIDES を読んだメモ
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"
nil
とfalse
以外の値はtrue
となる
if と unless
- ひとつの条件だけを検証したい時に用いる
false
とnil
が条件の時は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