概要
Elixirの対話モードでtryとcatchおよびrescueの動作を確認してみました。以下のページを参考にしました。
対話モードで実行
以下のコマンドを実行しました。
$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]
Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :atom + 1
** (ArithmeticError) bad argument in arithmetic expression: :atom + 1
:erlang.+(:atom, 1)
iex(1)> raise "oops"
** (RuntimeError) oops
iex(1)> raise(ArgumentError, message: "invalid argument")
** (ArgumentError) invalid argument
iex(1)> defmodule MyError do
...(1)> defexception message: "default message"
...(1)> end
{:module, MyError,
<<70, 79, 82, 49, 0, 0, 13, 88, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 88,
0, 0, 0, 34, 14, 69, 108, 105, 120, 105, 114, 46, 77, 121, 69, 114, 114, 111,
114, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, :ok}
iex(2)> raise MyError
** (MyError) default message
iex(2)> raise MyError, message: "custom message"
** (MyError) custom message
iex(2)> try do
...(2)> raise MyError
...(2)> rescue
...(2)> err in MyError -> err
...(2)> end
%MyError{message: "default message"}
iex(3)> try do
...(3)> raise "oops"
...(3)> rescue
...(3)> err in RuntimeError -> err
...(3)> end
%RuntimeError{message: "oops"}
iex(4)> try do
...(4)> raise "oops"
...(4)> rescue
...(4)> RuntimeError -> "Error!"
...(4)> end
"Error!"
iex(5)> File.read "hello"
{:error, :enoent}
iex(6)> File.write "hello", "world"
:ok
iex(7)> File.read "hello"
{:ok, "world"}
iex(8)> defmodule Example do
...(8)> def read_file(file) do
...(8)> case File.read file do
...(8)> {:ok, body} -> IO.puts "Success: #{body}"
...(8)> {:error, reason} -> IO.puts "Error: #{reason}"
...(8)> end
...(8)> end
...(8)> end
{:module, Example,
<<70, 79, 82, 49, 0, 0, 7, 8, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 228, 0,
0, 0, 24, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:read_file, 1}}
iex(9)> Example.read_file("hello")
Success: world
:ok
iex(10)> Example.read_file("unknown")
Error: enoent
:ok
iex(11)> File.read! "unknown"
** (File.Error) could not read file "unknown": no such file or directory
(elixir 1.12.2) lib/file.ex:355: File.read!/1
iex(11)> try do
...(11)> for x <- 0..10 do
...(11)> if x > 4, do: throw(x)
...(11)> IO.puts(x)
...(11)> end
...(11)> catch
...(11)> x -> "Caught: #{x}"
...(11)> end
0
1
2
3
4
"Caught: 5"
iex(12)> Enum.find(0..10, &(&1 > 4))
5
iex(13)> spawn_link fn -> exit("oh no") end
** (EXIT from #PID<0.106.0>) shell process exited with reason: "oh no"
Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> try do
...(1)> exit "oh no!"
...(1)> catch
...(1)> :exit, _ -> "exit blocked"
...(1)> end
"exit blocked"
iex(2)> try do
...(2)> raise "Oh no!"
...(2)> rescue
...(2)> err in RuntimeError -> IO.puts("An error occurred: " <> err.message)
...(2)> after
...(2)> IO.puts "The end!"
...(2)> end
An error occurred: Oh no!
The end!
:ok
iex(3)> defmodule Example do
...(3)> def handle_file(path, string) do
...(3)> {:ok, file} = File.open(path, [:utf8, :write])
...(3)> try do
...(3)> IO.write file, string
...(3)> raise "oops, something went wrong"
...(3)> after
...(3)> File.close(file)
...(3)> IO.puts "the file is closed"
...(3)> end
...(3)> end
...(3)> end
warning: redefining module Example (current version defined in memory)
iex:3
{:module, Example,
<<70, 79, 82, 49, 0, 0, 7, 20, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 228,
0, 0, 0, 24, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:handle_file, 2}}
iex(4)> Example.handle_file("hello", "world")
the file is closed
** (RuntimeError) oops, something went wrong
iex:8: Example.handle_file/2
iex(4)> defmodule RunAfter do
...(4)> def without_even_trying do
...(4)> raise "oops"
...(4)> after
...(4)> IO.puts "cleaning up!"
...(4)> end
...(4)> end
{:module, RunAfter,
<<70, 79, 82, 49, 0, 0, 5, 248, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 205,
0, 0, 0, 19, 15, 69, 108, 105, 120, 105, 114, 46, 82, 117, 110, 65, 102, 116,
101, 114, 8, 95, 95, 105, 110, 102, 111, ...>>, {:without_even_trying, 0}}
iex(5)> RunAfter.without_even_trying
cleaning up!
** (RuntimeError) oops
iex:6: RunAfter.without_even_trying/0
iex(5)> x = 2
2
iex(6)> try do
...(6)> 1 / x
...(6)> rescue
...(6)> ArithmeticError ->
...(6)> :infinity
...(6)> else
...(6)> y when y < 1 and y > -1 ->
...(6)> :small
...(6)> _ ->
...(6)> :large
...(6)> end
:small
iex(7)> what_happened = :outside
:outside
iex(8)> try do
...(8)> raise "fail"
...(8)> what_happened = :did_not_raise
...(8)> rescue
...(8)> _ -> what_happened = :rescued
...(8)> end
warning: variable "what_happened" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)
iex:10
warning: variable "what_happened" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)
iex:12
:rescued
iex(9)> what_happened
:outside
iex(10)> what_happened =
...(10)> try do
...(10)> raise "fail"
...(10)> :did_not_raise
...(10)> rescue
...(10)> _ -> :rescued
...(10)> end
:rescued
iex(11)> what_happened
:rescued
iex(12)>
まとめ
何かの役に立てばと。