読者です 読者をやめる 読者になる 読者になる

Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

急いで覚えるElixir: 制御構文編

テクノロジー

Elixirの基本制御構文

前回の記事から続いて、今回はElixirで利用する基本的な制御構文について学んでいきます。

if, unless/else

他のプログラミング言語で親しまれているif~elseは、Elixirでは以下のように記述します。

iex> if true do
...>   "みえる"
...> else
...>   "みえない"
...> end
"みえる"

ifをunlessに変えることで、条件を反転させることが出来ます。

case

case文は以下のように記述します。

iex> case {1, 2, 3} do
...>   {4, 5, 6} ->
...>     "この条件にはマッチしない"
...>   {1, x, 3} ->
...>     "この条件にマッチして、この文のスコープ変数xに2が代入される"
...>   _ ->
...>     "_ はどの条件にもマッチする"
...> end
"この条件にマッチして、この文のスコープ変数xに2が代入される"

cond

case文は幾つかの値の中でマッチするのもを探しだすのに便利ですが、幾つかの条件の中で最初にマッチするものを探し出したい場合もあります。 このようなときは、cond文を使用します。

iex> cond do
...>   2 + 2 == 5 ->
...>     "ちがう"
...>   2 * 2 == 3 ->
...>     "これもちがう"
...>   1 + 1 == 2 ->
...>     "これだ!"
...> end
"これだ!"

上から評価されますが、最後までマッチされなかった時はエラーになります。

iex> cond do
...> 1 + 2 == 2 ->
...> "wow"
...> end
** (CondClauseError) no cond clause evaluated to a true value

do/end ブロック

Elixirもrubyのようにdo/endでブロックを定義することが出来ます。 do/endブロックで注意しないといけないのは、もっとも外側の関数の呼び出しに対してバインドされる点です。すなわち、以下の例は、

iex> is_number if true do
...>  1 + 2
...> end

以下のようにパースされることになります。

iex> is_number(if true) do
...>  1 + 2
...> end
** (RuntimeError) undefined function: if/1

また、ブロック内で定義された変数などは、ブロック外からはスコープ外になります。

raise

Elixirもrubyのようにraise句でエラーを発生させることが出来ます。 デフォルトはRuntimeErrorです。

iex> raise "oops"
** (RuntimeError) oops

エラーを独自に定義して、raiseの引数で指定することも出来ます。

iex> defmodule MyError do
iex>   defexception message: "default message"
iex> end
iex> raise MyError, message: "custom message"
** (MyError) custom message

rescue

エラーを補足するにはrescue句を利用します。

iex> try do
...>   raise "oops"
...> rescue
...>   e in RuntimeError -> e
...> end
%RuntimeError{message: "oops"}

throw/catch

Elixirで大域脱出を行うにはthrow/catchを利用します。 throwで値を投げ、catchで補足します。

iex> try do
...>   Enum.each -50..50, fn(x) ->
...>     if rem(x, 13) == 0, do: throw(x)
...>   end
...>   "Got nothing"
...> catch
...>   x -> "Got #{x}"
...> end
"Got -39"

after

after句で、rubyのensureのように、try句の終了直前に必ず実行する処理を記述することが出来ます。

iex> try do
...>   IO.puts "try!"
...>   raise   "raise!!"
...> after
...>   IO.puts "after!!!"
...> end
try!
after!!!
** (RuntimeError) raise!!

exit

すべてのElixirコードは互いに通信し合うプロセス上で動いています。 プロセスが「自然死」する場合(例えば未処理の例外が起きた時)、exitシグナルを送ります。 また、手動でexitシグナルを送ることでプロセスを殺すこともできます。

try do
  exit "急いで覚える"
catch
  :exit, _ -> "Elixir"
end
"Elixir"

exitは前述のtry/catchで補足することも出来ます。

まとめ

Elixirの基本的な制御構文を学ぶことが出来ました。 より詳しく知りたい方は、以下の公式ドキュメントからよりカッコイイ書き方を知ることが出来ます。(外部サイトへ飛びます。)