[swift-evolution] Throws? and throws!
xiaodi.wu at gmail.com
Thu Jan 12 18:27:18 CST 2017
On Thu, Jan 12, 2017 at 6:17 PM, Jonathan Hull <jhull at gbis.com> wrote:
> On Jan 12, 2017, at 3:35 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution <
> swift-evolution at swift.org> wrote:
>> I really like swift’s error handling system overall. It strikes a good
>> balance between safety and usability.
>> There are some cases where it would be nice to throw errors, but errors
>> are rarely expected in most use cases, so the overhead of ‘try’, etc… would
>> make things unusable. Thus fatalError or optionals are used instead. For
>> example, operators like ‘+’ could never throw because adding ’try’
>> everywhere would make arithmetic unbearable. But in a few cases it would
>> make my algorithm much cleaner if I just assume it will work and then catch
>> overflow/underflow errors if they happen, and resolve each of them with
>> special cases. Or perhaps I am dealing with user entered values, and want
>> to stop the calculation and display a user visible error (e.g. a symbol in
>> a spreadsheet cell) instead of crashing.
> Unless I'm mistaken, there is a performance overhead for throwing
> functions, and thus a much greater barrier to the use cases outlined above
> is that the performance penalty for '+' would be unacceptable in any case,
> whatever syntactic sugar you could come up with.
> I think that is an invalid assumption. I don’t think we should limit our
> proposals based on the performance of the naive/brute-force implementation.
> I am sure there are lots of tricks the compiler could pull if performance
> is an issue. Off the top of my head, although the user model is that it
> adds “try!” before the function, it could actually make two different
> versions of the function (one with fatalError and the other with error
> handling) and insert the right one based on how it is called.
Sure, that's not the meat of why I'm uncomfortable with the idea. I am
saying, however, that you've outlined as motivation two use cases here that
your proposal does not make possible.
> I would like to propose adding ‘throws?’ and ‘throws!’ variants to
>> These would be used for cases where error handling is not the default
>> desired behavior, but having it as an option is desired occasionally.
> While I admit the idea has an appeal on a practical level, I have an
> uncomfortable feeling about this. It's by definition true that error
> handling is never the default desired behavior, and if I recall correctly
> the performance of Swift error handling is tuned on the assumption that not
> throwing is far more common than throwing. If we accept this statement at
> face value as the justification for including `throws!`, then essentially
> all `throws` should be `throws!`. And indeed I suspect that if the feature
> were be implemented, that would rapidly become the case in much written
> Swift. In essence, then, I think you're effectively proposing to invert the
> assignment of responsibility for determining how errors are handled from
> the call site to the declaration site, at least by default. It goes against
> an overarching design principle in Swift (discussed earlier in the thread
> about DefaultConstructible) not to provide such defaults and to require
> explicitness at the call site.
> I would argue that it allows the framework designer a lot of
> expressiveness about what they feel the correct approach is. By using
> ‘throws’, ‘throws?’, or ‘throws!’, they are able to require explicitness or
> not depending on how they expect the framework to be used. There is still
> a lot of value to plain old ‘throws’ (namely where I need the user to
> consider the possibility of error), and I would continue to use it for most
> cases. It is the cases where I have been forced to use fatalError, where I
> would use ‘throws!’.
Have a gander at this document:
In particular, have a look at the section titled "Kinds of error." I think
what you're describing here is that you've got something that's neither a
simple domain error nor a recoverable error, as classically described. And
you'll see that there are some kinds of error for which Swift doesn't
currently have a good answer. I'd be interested in some real-world use
cases, though, and a more holistic approach to these other kinds of error
would be called for. It's why I'm saying you've got the beginning of an
interesting idea, but it's a lot more involved than you're making it out to
While mistake prevention is a worthy goal which I support fully, there is a
> difference between preventing programming errors and trying to enforce
> one’s coding philosophy on everyone. I would argue for things like this,
> we should favor expressiveness and then trust framework designers to use
> that expressiveness responsibly. I might argue differently in cases where
> there was a high probability of foot-gunning, but I don’t feel like this is
> one of those cases. It is a choice made by the framework designer (just
> like they can make a class ‘open’ or not), and the good designers will use
> it well.
> I would also add that all of your arguments apply equally well to ‘as!’
> and forced unwrapping using ‘!’ which are both things that swift includes.
> Thus I don’t think it is a overarching design principle of swift as you
> claim. Rather we have safety by default, with the ability to override.
My arguments haven't been expressed very clearly, then, if you think that
they support such an interpretation. Instead, `as!` and `!` are analogous
to `try!`: they are used at the call site to statically assert something.
By contrast, your proposal is essentially to have these inferred silently,
as a default supplied at the declaration site. There is a distinction
between these two, and as pointed out in the other conversation referenced
above, Swift is said to choose call site clarity over defaults as a general
> Essentially, the user would no longer have to preface the call with ‘try’,
>> as the compiler would implicitly add ‘try?’ or ‘try!’ respectively.
>> Thus, the function would act like a non-throwing function (either
>> trapping or returning an optional in the case of error), but the user could
>> add ‘try’ to the call to override that behavior and deal with the error
>> more explicitly.
>> Another example would be bounds checking on arrays. If subscripting
>> arrays was marked as ‘throws!’ then it would have the same default behavior
>> it does now (trapping on bounds error). But a user could add ‘try?’ to
>> return nil for a bounds error in cases where they explicitly want that, or
>> they could add ‘try’ to deal with it as an error using do-catch.
> Subscripts cannot throw at all at the moment, and in another thread some
> of the challenges for designing throwing subscripts were just mentioned. I
> suspect any sort of throwing subscript will not be possible in the
> immediate future, so the argument for `throws!` here is moot.
> On the contrary, it is on the roadmap, and thus is something we should
> plan for.
It is not, as far as I'm aware, the plan of record in any sense; it has not
been proposed and is not an identified priority of this phase of Swift 4
If we consider each feature only in isolation then we will end up with a
> fractured mess like C++.
> I think this would really increase the availability of error handling in
>> areas where it is impractical right now…
> I think the practical argument could be made stronger by use cases not
> encumbered by other difficulties as outlined above. Is there a currently
> throwing function you've encountered that would be greatly improved by such
> a feature? Besides that, though, my discomfort is (as mentioned above) that
> the practical effect of such a feature is that it will actually altogether
> invert the default responsibility for error handling, and I'm not sure that
> it's entirely consistent with Swift's design as a consequence. In any case
> it'd be a far greater change than you've made it out to be. Interesting
> suggestion, definitely.
>> swift-evolution mailing list
>> swift-evolution at swift.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution