[swift-evolution] Throws? and throws!

Xiaodi Wu 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
>> ‘throws’.
>>
>> 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:
https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst

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
be.

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
overarching principle.

> 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
for proposal.

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.
>
> Thanks,
>> Jon
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170112/b0310602/attachment.html>


More information about the swift-evolution mailing list