官术网_书友最值得收藏!

  • Mastering Elixir
  • André Albuquerque Daniel Caixinha
  • 571字
  • 2021-08-05 10:42:49

Exceptions

Much like if and else, exceptions in Elixir aren't used as much as in other popular imperative languages. Exceptions aren't used for control flow, and are left for when truly exceptional things occur. When they do, your process is usually running under a supervision tree, and upon crashing, the supervisor of your process will be notified and (possibly, depending on the strategy) restart it. Then, upon being restarted, you're back to a known and stable state, and the effects of the exceptional event are no longer present. In the Elixir and Erlang communities, this is usually referred to as the "Let it crash!" philosophy. We'll be examining this in greater detail in Chapter 3, ProcessesThe Bedrock for Concurrency and Fault Tolerance, when we talk about processes, supervisors, and supervision trees.

For now, I'll list the traditional error-handling constructs. You can raise an error with the raise construct, which takes one or two arguments. If you provide only one argument, it will raise a RuntimeError, with the argument as the message. If you provide two arguments, the first argument is the type of error, while the second is a keyword list of attributes for that error (all errors must at least accept the message: attribute). Let's see this in action:

iex> raise "Something very strange occurred"
** (RuntimeError) Something very strange occurred
iex> raise ArithmeticError, message: "Some weird math going on here"
** (ArithmeticError) Some weird math going on here

You can rescue an error by using the rescue construct (you can rescue from a try block or from a whole function, pairing it with def). You define patterns on the rescue clause. You can use _ to match on anything. If none of the patterns match, the error will not be rescued and the program will behave as if no rescue clause was present:

iex> try do
...> 5 / 0
...> rescue
...> e in ArithmeticError -> "Tried to divide by 0."
...> _ -> "None of the above matched"
...> end
"Tried to divide by 0."

Since we're not doing anything with the error, and just returning a string, we could just use ArithmeticError in the pattern. Only use this syntax if you want to capture the error itself. When none of the patterns match, we get the error back in our console:

iex> try do
...> 5 / 0
...> rescue
...> ArgumentError -> "ArgumentError was raised."
...> end
** (ArithmeticError) bad argument in arithmetic expression

Furthermore, you can also pass an else and/or an after block to the try/rescue block. The else block will match on the results of the try body when it finishes without raising any error. As for the after construct, it will always get executed, regardless of the errors that were raised. This is commonly used to clean up some resources (closing a file descriptor, for instance).

We've mentioned in this section that we don't use exceptions to control the flow of our programs, but in fact there's a special construct in Elixir for this. The syntax is similar to the one shown earlier, but you use throw instead of raise, and catch instead of rescue. As mentioned in the official Getting Started guide ( http://elixir-lang.github.io/getting-started/try-catch-and-rescue.html) this should be used in situations where it is not possible to retrieve a value unless by using throw and catch. It's also mentioned that those situations are quite uncommon in practice.
主站蜘蛛池模板: 怀仁县| 涪陵区| 城口县| 合江县| 兴城市| 白玉县| 扎兰屯市| 宣威市| 沈阳市| 南雄市| 垦利县| 仙游县| 隆昌县| 新泰市| 高陵县| 拉孜县| 苍山县| 佛山市| 莆田市| 淮北市| 延长县| 南宫市| 新丰县| 石屏县| 玉屏| 天长市| 莱阳市| 广南县| 关岭| 文昌市| 镇远县| 西峡县| 新巴尔虎左旗| 正阳县| 珲春市| 华亭县| 蓝山县| 霍州市| 梁河县| 菏泽市| 晋宁县|