7 Miscellaneous Features
7.1 Error Handling
Before we can handle errors we need to create them and the simplest way to do so is with raise/1:
iex> raise "Oh no!"
#> ** (RuntimeError) Oh no!If we want to specify the type and message, we need to use raise/2:
iex> raise ArgumentError, message: "the argument value is invalid"
#> ** (ArgumentError) the argument value is invalidWhen we know an error may occur, we can handle it using try/rescue and pattern matching:
try do
raise "Oh no!"
rescue
e in RuntimeError -> IO.puts("An error occurred: " <> e.message)
end
#> An error occurred: Oh no!
#> :okIt’s possible to match multiple errors in a single rescue:
try do
opts
|> Keyword.fetch!(:source_file)
|> File.read!()
rescue
e in KeyError -> IO.puts("missing :source_file option")
e in File.Error -> IO.puts("unable to read source file")
endAt times it may be necessary to perform some action after our try/rescue regardless of error. For this we have try/after.
try do
raise "Oh no!"
rescue
e in RuntimeError -> IO.puts("An error occurred: " <> e.message)
after
IO.puts "The end!"
end
# An error occurred: Oh no!
# The end!
# :okThis is most commonly used with files or connections that should be closed:
{:ok, file} = File.open("example.json")
try do
# Do hazardous work
after
File.close(file)
end7.2 Sigils
7.2.1 ~r: regular expressions
iex > regex <- ~ r/foo|bar/
iex > "foo" <- ~regex
#> true
iex > "bat" <- ~regex
#> false7.2.2 Strings, char lists and word list sigils
7.2.2.1 Strings
The ~s sigil is used to generate strings, like double quotes are. The ~s sigil is useful when a string contains double quotes:
iex> ~s(this is a string with "double" quotes, not 'single' ones)
#> "this is a string with \"double\" quotes, not 'single' ones"7.2.2.2 Char lists
The ~c sigil is useful for generating char lists that contain single quotes:
iex> ~c(this is a char list containing 'single quotes')
#> 'this is a char list containing \'single quotes\''7.2.2.3 Word lists
The ~w sigil is used to generate lists of words (words are just regular strings). Inside the ~w sigil, words are separated by whitespace.
iex> ~w(foo bar bat)
#> ["foo", "bar", "bat"]The ~w sigil also accepts the c, s and a modifiers (for char lists, strings, and atoms, respectively), which specify the data type of the elements of the resulting list:
iex> ~w(foo bar bat)a
#> [:foo, :bar, :bat]7.2.3 Calendar Sigils
7.2.4 Custom Sigiils
As hinted at the beginning of this chapter, sigils in Elixir are extensible. In fact, using the sigil ~r/foo/i is equivalent to calling sigil_r with a binary and a char list as the argument:
iex> sigil_r(<<"foo">>, 'i')
#> ~r"foo"iWe can also provide our own sigils by implementing functions that follow the sigil_{character} pattern. For example, let’s implement the ~i sigil that returns an integer (with the optional n modifier to make it negative):
iex> defmodule MySigils do
...> def sigil_i(string, []), do: String.to_integer(string)
...> def sigil_i(string, [?n]), do: -String.to_integer(string)
...> end
iex> import MySigils
iex> ~i(13)
#> 13
iex> ~i(42)n
#> -42Sigils can also be used to do compile-time work with the help of macros. For example, regular expressions in Elixir are compiled into an efficient representation during compilation of the source code, therefore skipping this step at runtime. If you’re interested in the subject, we recommend you learn more about macros and check out how sigils are implemented in the Kernel module (where the sigil_* functions are defined).