>Throws in Swift are not traditional exceptions. A throwing function in Swift is actually a function that can return an error instead of a result. This is hidden by the language.
Using the normal return path vs. nonlocal returns is, I think, not equivalent unless you have a GC. Otherwise you need all that "exception safe code" stuff.
But the main difference is it's not hidden by the language; you have to 'try' any method that can return an error. Straight-line control flow in an imperative language is a good thing IMO. …but too bad about those defer statements.
>Using the normal return path vs. nonlocal returns is, I think, not equivalent unless you have a GC.
I will repeat, whether exceptions are implemented as "nonlocal returns" (like setjmp/longjmp with stack unwinding) or as syntax sugar with sum return types, is completely irrelevant; an implementation detail. The generated machine code is different, but the behavior, the user experience is exactly the same.
>Otherwise you need all that "exception safe code" stuff.
In both cases, you need to write "exception safe code". Example of unsafe code in Java (a language that implements exceptions as non-local returns):
>But the main difference is it's not hidden by the language; you have to 'try' any method that can return an error. Straight-line control flow in an imperative language is a good thing IMO. …but too bad about those defer statements.
Whether the language makes you prefix throwing calls with "try" is completely orthogonal to how they're implemented (nonlocal return vs sum return type). It's just a matter of syntax.
Implementation detail.
The two features are equivalent.