Erlang中throw与catch的差异及适用场景技术咨询
Hey there! Let's break down when to use throw and catch in Erlang, using your code example to make things concrete.
First, let's clarify that Dialyzer warning you saw: when you used throw({error, "Input error"}) in is_odd/1, Dialyzer flagged that the Result variable in sum/2 can never match. That's because if A isn't an integer, throw doesn't return a value to the case statement—it jumps straight out of the current execution flow as an exception. Adding a catch around the is_odd(A) call fixes this because catch captures the exception and converts it into a return value, making that Result clause reachable again.
Now let's dive into the use cases:
When to use throw
- Expected business logic exceptions: Use
throwfor error conditions you anticipate in your application flow, but which need to break out of the current function to be handled by an upstream caller. For example, ifis_odd/1is part of a pipeline where invalid inputs should be caught by a higher-level module (not handled right insum/2),throwmakes sense—it signals, "This input is invalid; stop what you're doing and let someone else handle this." - Controlled error propagation:
throwis lighter weight thanerrororexit(which are meant for system-level failures or process termination). It's designed for situations where you want to pass an error up the call stack without crashing the entire process—as long as there's a catch waiting upstream. - Critical note: Never use
throwwithout ensuring there's a correspondingcatch(ortry...catch) in the call chain. Unhandledthrowwill crash your process just like any other uncaught exception.
When to use catch (or explicit error returns)
In your case, "using catch" likely means either wrapping the throw-ing call in a catch to convert exceptions into return values, or ditching throw entirely and returning an error tuple like {error, ...} directly. Either way, here's when this approach is better:
- Local error handling: If the error can be handled immediately in the calling function (like your
sum/2), returning an explicit error value (or usingcatchto capture the throw) lets you handle it synchronously in thecasestatement. This makes the code easier to reason about and keeps control flow clear. - Dialyzer compliance: As you experienced, using return values instead of escaping exceptions makes your code's type contracts unambiguous. Dialyzer can verify all code paths are reachable, which helps catch bugs early.
- Readability & efficiency: For common error cases, returning explicit error tuples is often more readable than relying on exceptions. It also avoids the small overhead of exception handling, which adds up for frequent errors.
- Handling unexpected exceptions:
catch(ortry...catch) is also useful for handling unexpected system errors (like a function crashing for an unforeseen reason), buttry...catchis usually more readable than the standalonecatchexpression for this purpose.
Quick recap
- Use
throwwhen you need to bubble an expected error up to an upstream handler and don't want to handle it locally. - Use
catch(or explicit error returns) when you can handle the error immediately in the calling code, or when you want to keep your code's control flow explicit for tools like Dialyzer and human readers.
内容的提问来源于stack exchange,提问作者tandathuynh148

