This document discusses the debate around using exceptions vs returning error values to handle errors in code. It notes some advantages of exceptions like those outlined by Oracle, but also disadvantages like performance penalties and issues with threading. It argues that languages with pattern matching and algebraic data types can return error values without these downsides, and notes examples in Erlang, Elixir, and Haskell. A summary is provided recommending using exceptions only for truly unexpected errors, and otherwise returning error values that can be handled normally.
2. The case for exceptions
“Advantages of Exceptions” - Oracle,
https://docs.oracle.com/javase/tutorial/essential/exceptions/advantages.html
3.
4.
5. The case against exceptions
● Slow
○ Some benchmark according to StackOverflow: “The slowdown from the try block is too small to
rule out confounding factors such as background processes. But the catch block killed everything
and made it 66 times slower!”
■ https://stackoverflow.com/questions/299068/how-slow-are-java-exceptions
● Nonlocal effects
○ Timeouts that use exceptions break threading models
■ https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-
terrifying/
● Rocky relationship w/ type systems
○ (frequently) You cannot see if a function throws an exception (NullReferenceException says hello)
■ Checked vs unchecked (java)
6. Errors without Exceptions
Can we do better than the nested if statements that Oracle used to show you the
horrors of treating errors as values?
7. Yes! (...in some languages)
These language level features help:
● Pattern matching
● Type system that doesn’t actively oppose algebraic data types
○ No type system
○ Good type system
■ union type
■ Intersection type
8. Side note: Java supports the union type
(But only in a catch block)
Maybe a result type can do this too? https://nbsoftsolutions.com/blog/a-java-result-
algebraic-data-type-worth-using
13. Benefits of Errors as values
● Don’t need extra type system concepts
● Faster (didn’t benchmark for erlang/elixir yet)
● “Easier to reason about” - Me
● (idiomatic in erlang/elixir/haskell)
14. Summary
When to use exceptions:
Unexpected situations - where you would normally have a server respond w/ status
code 500: server error, something went wrong, that’s all we know :(
15. Summary
All other times, for things that can go wrong but can be healthfully handled:
Return a result! Either a successful result or return a description of what went wrong
File.read/1 returns {:ok, binary()} | {:error, posix()}
Notes de l'éditeur
This is what oracle says is bad when they defend exceptions.
This *is* better than the nested if-statement situation!
In particular, the lack of pyramid of doom left indent is a big improvement.
But I think we can do better.
Some languages w/ support for pattern matching include:
Haskell/Elm, Erlang/Elixir, Rust, Swift, scala
Some languages w/ type support for the union types are:
Scala, Swift, Rust, Haskell/Elm/Purescript, Idris, F#, Flow/Typescript, Erlang/Elixir (but not really a type system)
Java doesn’t really give this concept the time of day - I’ve never actually seen these types of things appear without class hierarchies, which requires the things you want to model to have the same superclass, but can sorta work.
Here is an example of both union type support in the type annotation and pattern matching in the function definition
This describes the happy path through the code and doesn’t indent, like Oracle’s example of the advantages of exceptions.
You will almost certainly want to transform the individual errors you can get to ones better for your consumer
So this looks very similar to the java + exceptions example to me, but emphasizes that errors are not exceptional