4 ms·
No. This is exactly wrong. Pattern matching on ok tuple is awful because you will get a generic MatchError with an inscrutable message that requires reseriali
by throwawaymaths 3y ago
No. This is exactly wrong.
Pattern matching on ok tuple is awful because you will get a generic MatchError with an inscrutable message that requires reserialization of the exception struct and not a more useful Error where you can have an informative Exception.message protocol implementation.
> All functions that can fail should return a tuple. For convenience, one might also add a ! version that raises.
This is absolutely good advice for library writers. But if you're using a library, most of the time, use the raising version.
- sph 3y agoYou don't get an inscrutable message. An example from Elixir docs: iex> {a, b, c} = {:hello, "world"} * (MatchError) no match of right hand side value: {:hello, "world"} The MatchError shows you the part that was not matching. When pattern matching on {:ok, value}, on match error you'd be told it doesn't match, say {:error, %DatabaseError{reason: "Server has gone away."}} I always pair my production Elixir apps with Sentry, which gives me a backtrace, so I have everything needed to track down an error. > But if you're using a library, most of the time, use the raising version. I use the raising version to explicitly "I want this to crash." So this would happen only at the edges of the system. All internal code should operate on tuples. You don't want a core, internal function to raise and have to catch it on higher-level modules, because that's terrible form. In other words, feel free to raise, as long as there is no one that has to catch the exception. If you raise, the goal is to crash, not to leverage exceptions as control flow. This isn't Java. I've been using Elixir since 2016 and I don't think I have written more than a couple exception handlers since.
- throwawaymaths 3y agoLol, have you never gotten an exception that wraps another exception in the error payload. Those are not fun to parse. I've also run into situations where the error reporting agent trims the error. Murphys law, always exactly a few bytes before the part you needed. Or, the key information is shortened by default limits on inspect or #SomeStruct<... Oops sorry I hid it> Anyways. The whole point of BEAM is that you code the happy path and if you can't actually do anything about the error, you're wasting effort and making your code harder to reason about. Nobody is suggesting using errors like control flow. Writing a try/rescue is indeed an antipattern. It's like the Toyota factory line. If something irrecoverable happens, just pull the emergency stop and start over. If you've been handling errors like that since 2016, well, I guess that's your choice, man. I wouldn't do it.