Re: [swift-evolution] Throws? and throws!

2017-01-16 Thread Callionica (Swift) via swift-evolution
One stray thread performing an overflowing addition can be the difference
between a secure system and an insecure one. Better to take the process
down.

-- Callionica

On Sun, Jan 15, 2017 at 10:48 PM Russ Bishop via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> I don’t think it makes sense to abort a server process (potentially
> dropping X threads and thousands of connections on the ground) because one
> stray thread performed an overflowing addition…
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-16 Thread Tino Heth via swift-evolution
> My intended framing of this does not seem to be coming across in my 
> arguments.  I am not thinking of this as a way to avoid typing ‘try!’ or 
> ‘try?’.  This is not intended to replace any of the current uses of ‘throws’. 
>  Rather, it is intended to replace trapping and nil-returning functions where 
> converting it to throw would be burdensome in the most common use cases, but 
> still desirable in less common use cases.  In my mind, it is only enabling 
> the author to provide extra information and flexibility, compared to the 
> current behavior.

I'm more or less neutral towards the proposal, but to express my perception, 
one part seems similar to the use of "!" in variable declarations (like IB 
does):
It just makes force unwrapping (or, here: assuming that no error happened) the 
default, but leaves all other options intact.

But Afaics, force unwrapped variables are considered a bad practice that should 
be avoided (nearly) wherever possible…

The "try?-replacement" could be more useful for me: In my codebase, I have 
several throwing functions paired with computed properties (returning an 
Optional of the same type) that directly map to them, and at the call site, I 
usually don't care about the error.

I'm not sure if it's useful enough to justify new syntactic sugar for it, 
though — especially as I think it's not very intuitive.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-15 Thread Russ Bishop via swift-evolution
I’m not sure I like this specific proposal, but the idea of having the option 
of catching a certain class of runtime errors is appealing.

I don’t think it makes sense to abort a server process (potentially dropping X 
threads and thousands of connections on the ground) because one stray thread 
performed an overflowing addition… one could always require use of 
addWithOverflow I suppose, but auditing code for “+” is a different kind of 
pain than auditing for UnsafeMutablePointer. For servers the operation is 
almost always bounded by a single request, so unwinding any transactions and 
aborting the thread is sufficient to recover. There will also be cases where 
cleanup on fatalError() is absolutely required; if Swift leaves dangling 
database transactions on abort it is not usable for a large number of scenarios 
(speaking from direct experience). 

Rust takes an interesting approach with panic and catch_unwind… at compile time 
you can make a policy decision that all panics are aborts or that 
non-catastrophic panics can be handled, but only by the parent thread. In our 
terminology that would be saying that precondition ends the current dispatch 
work item and only the parent queue can handle the failure. This gets very 
tricky to even describe because it doesn’t map cleanly to libDispatch and we 
don’t have the compiler support to enforce cross-queue boundaries right now, so 
there is the potential to leak memory (which is OK for infrequent panics) or 
corrupt memory (unacceptable).

My guess is we could do something like this and in fact will need to do 
something like this, but only when we have a good concurrency story enforced by 
the compiler.

Russ

> On Jan 12, 2017, at 2:58 PM, Jonathan Hull via swift-evolution 
>  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.
> 
> 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.  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.
> 
> I think this would really increase the availability of error handling in 
> areas where it is impractical right now…
> 
> Thanks,
> Jon
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-15 Thread Xiaodi Wu via swift-evolution
On Sun, Jan 15, 2017 at 3:12 PM, Haravikk 
wrote:

>
> On 12 Jan 2017, at 23:35, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution <
> swift-evolution@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.
>
>
> Just wanted to chime in on performance, but since operators should really
> be inlined in most cases anyway I'm not sure there should be any
> performance penalty; the compiler should just optimise it away such that it
> basically becomes what it is now, the only case in which it would add a
> penalty is if the optional try is actually used.
>
>
> I really like this idea personally; I prefer it to using the
> addWithOverflow() and similar methods, not that they're super burdensome,
> but error handling feels like a better fit IMO.
>

`addWithOverflow()` gives you both the result and a flag; error handling
would at most give you one of these two. If that's a common use case, it'd
be an argument for a failable addition operator, but not a throwing one,
since there is only one error that happens (overflow).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-15 Thread Haravikk via swift-evolution

> On 12 Jan 2017, at 23:35, Xiaodi Wu via swift-evolution 
> > wrote:
> 
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution 
> > 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.

Just wanted to chime in on performance, but since operators should really be 
inlined in most cases anyway I'm not sure there should be any performance 
penalty; the compiler should just optimise it away such that it basically 
becomes what it is now, the only case in which it would add a penalty is if the 
optional try is actually used.


I really like this idea personally; I prefer it to using the addWithOverflow() 
and similar methods, not that they're super burdensome, but error handling 
feels like a better fit IMO.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-14 Thread Xiaodi Wu via swift-evolution
On Sat, Jan 14, 2017 at 10:10 PM, Jonathan Hull  wrote:

> And finally, even if an operator function could fail in multiple ways
> (we're really getting to very hypothetical hypotheticals here), writing
> `try!` all the time might look silly and non-Swift users might then mock
> the language, but I dispute the contention that it would make things
> "unbearable.”
>
>
> The whole point of ‘try’/’try!’ is to make the user consider how to handle
> the error cases.  If it gets used everywhere, then you have a boy who cried
> wolf situation where it is seen as noise and ignored… which definitely
> affects usability. (Take Windows' error dialogs as an example of this
> phenomenon).
>
>
In a hypothetical world where + was throwing, that would be a fair point,
and it would be something to balance against Greg's argument that `try!`
and `!` have value because they show all potential crash points at the
point of use. However, as this is very much a hypothetical, the more
salient point here is that there _aren't_ so many things that have multiple
meaningfully distinct ways of recovering from error.

In this present version of Swift, practical experience shows that if
anything people pay great amounts of attention (maybe too much) to
statements with `!`, even so far as to try to forbid it in their house
style (definitely too extreme, IMO)! Meanwhile, `try?` simply can't be
ignored because the type system makes you unwrap the result at some point
down the line.

On Jan 14, 2017, at 7:29 PM, Xiaodi Wu  wrote:
>
> On Sat, Jan 14, 2017 at 8:03 PM, Jonathan Hull  wrote:
>
>> My intended framing of this does not seem to be coming across in my
>> arguments.  I am not thinking of this as a way to avoid typing ‘try!’ or
>> ‘try?’.  This is not intended to replace any of the current uses of
>> ‘throws’.  Rather, it is intended to replace trapping and nil-returning
>> functions where converting it to throw would be burdensome in the most
>> common use cases, but still desirable in less common use cases.  In my
>> mind, it is only enabling the author to provide extra information and
>> flexibility, compared to the current behavior.
>>
>> For example, let’s say I have a failable initializer, which could fail
>> for 2 or 3 different reasons, and that the vast majority of use-cases I
>> only care whether it succeeded or not (which is why nil-returning was
>> chosen)… but there may be a rare case or two where I really would prefer to
>> probe deeper (and changing it to a throwing initializer would inhibit the
>> majority cases).  Then using ’throws?’ allows the primary usage to remain
>> unchanged, while allowing users to opt-in to throwing behavior when desired.
>>
>> Right now I end up making multiple functions, which are identical except
>> for throw vs nil-return, and must now be kept in sync.  I’ll admit it isn’t
>> terribly common, but it has come up enough that I think it would still be
>> useful.
>>
>
> As you say, I think this is a pretty niche use case. When you are in
> control of the code, it's trivial to write a second function that wraps the
> throwing function, returning an optional value on error. The only thing
> you'd need to keep in sync would be the declaration, not the function body,
> and that isn't truly onerous on the rare occasion when this is at issue.
>
>
>> The other argument I will make is one of symmetry.  We have 3 different
>> types of error handling in swift: throwing, optional-returns, and trapping.
>>
>
> As the Error Handling Rationale document has pointed out, these three
> different types of error handling are meant for different _kinds_ of error.
> The idea is that ideally the choice of what kind of error handling to use
> shouldn't be down to taste or other arbitrary criteria, but should reflect
> whether we're dealing with a recoverable error (throws), simple domain
> error (return nil), or logical error (trap). That much can be determined at
> the point of declaration. At the use site, there are tools to allow the end
> user to handle these errors in a variety of ways, but there is a logic
> behind allowing conversions between some and not all combinations:
>
> * A logical error is meant to be unrecoverable and thus cannot be
> converted to either nil or throw. To call a function that traps is to
> assert that the function's preconditions are met. If it's a possibility
> that the preconditions cannot be met, it should be handled before calling
> the function. A trap represents a programming mistake that should be fixed
> by changing the code so as not to trap. There are adequate solutions to the
> few instances where an error that currently traps might not be always have
> to be fatal: in the case of array indices, for instance, there's been
> proposals to allow more lenient subscripting that don't trap, at the cost
> of extra overhead--of course, you can already implement this for yourself
> in an extension.
>
> * A simple domain error 

Re: [swift-evolution] Throws? and throws!

2017-01-14 Thread Jonathan Hull via swift-evolution
> And finally, even if an operator function could fail in multiple ways (we're 
> really getting to very hypothetical hypotheticals here), writing `try!` all 
> the time might look silly and non-Swift users might then mock the language, 
> but I dispute the contention that it would make things "unbearable.”

The whole point of ‘try’/’try!’ is to make the user consider how to handle the 
error cases.  If it gets used everywhere, then you have a boy who cried wolf 
situation where it is seen as noise and ignored… which definitely affects 
usability. (Take Windows' error dialogs as an example of this phenomenon).



> On Jan 14, 2017, at 7:29 PM, Xiaodi Wu  wrote:
> 
> On Sat, Jan 14, 2017 at 8:03 PM, Jonathan Hull  > wrote:
> My intended framing of this does not seem to be coming across in my 
> arguments.  I am not thinking of this as a way to avoid typing ‘try!’ or 
> ‘try?’.  This is not intended to replace any of the current uses of ‘throws’. 
>  Rather, it is intended to replace trapping and nil-returning functions where 
> converting it to throw would be burdensome in the most common use cases, but 
> still desirable in less common use cases.  In my mind, it is only enabling 
> the author to provide extra information and flexibility, compared to the 
> current behavior.
> 
> For example, let’s say I have a failable initializer, which could fail for 2 
> or 3 different reasons, and that the vast majority of use-cases I only care 
> whether it succeeded or not (which is why nil-returning was chosen)… but 
> there may be a rare case or two where I really would prefer to probe deeper 
> (and changing it to a throwing initializer would inhibit the majority cases). 
>  Then using ’throws?’ allows the primary usage to remain unchanged, while 
> allowing users to opt-in to throwing behavior when desired.
> 
> Right now I end up making multiple functions, which are identical except for 
> throw vs nil-return, and must now be kept in sync.  I’ll admit it isn’t 
> terribly common, but it has come up enough that I think it would still be 
> useful.
> 
> As you say, I think this is a pretty niche use case. When you are in control 
> of the code, it's trivial to write a second function that wraps the throwing 
> function, returning an optional value on error. The only thing you'd need to 
> keep in sync would be the declaration, not the function body, and that isn't 
> truly onerous on the rare occasion when this is at issue.
> 
> 
> The other argument I will make is one of symmetry.  We have 3 different types 
> of error handling in swift: throwing, optional-returns, and trapping.
> 
> As the Error Handling Rationale document has pointed out, these three 
> different types of error handling are meant for different _kinds_ of error. 
> The idea is that ideally the choice of what kind of error handling to use 
> shouldn't be down to taste or other arbitrary criteria, but should reflect 
> whether we're dealing with a recoverable error (throws), simple domain error 
> (return nil), or logical error (trap). That much can be determined at the 
> point of declaration. At the use site, there are tools to allow the end user 
> to handle these errors in a variety of ways, but there is a logic behind 
> allowing conversions between some and not all combinations:
> 
> * A logical error is meant to be unrecoverable and thus cannot be converted 
> to either nil or throw. To call a function that traps is to assert that the 
> function's preconditions are met. If it's a possibility that the 
> preconditions cannot be met, it should be handled before calling the 
> function. A trap represents a programming mistake that should be fixed by 
> changing the code so as not to trap. There are adequate solutions to the few 
> instances where an error that currently traps might not be always have to be 
> fatal: in the case of array indices, for instance, there's been proposals to 
> allow more lenient subscripting that don't trap, at the cost of extra 
> overhead--of course, you can already implement this for yourself in an 
> extension.
> 
> * A simple domain error fails in only one obvious way and doesn't need an 
> error; the end user can always decide that a failure should be handled by 
> trapping using `!`--in essence, the user is asserting that the occurrence of 
> a simple domain error at that use site is a logical error. It shouldn't be 
> useful to convert nil to an error, because a simple domain error should be 
> able to fail in only one way; if the function fails in more than one way, the 
> function should throw, as it's no longer a simple domain error.
> 
> * A recoverable error can fail in one or more ways, and how you recover may 
> depend on how it failed; a user can always decide that they'll always recover 
> in the same way by using `try?`, or they can assert that it's a logical error 
> to fail at all using `try!`. The choice is up to the user.
> 
> As 

Re: [swift-evolution] Throws? and throws!

2017-01-14 Thread Xiaodi Wu via swift-evolution
On Sat, Jan 14, 2017 at 8:03 PM, Jonathan Hull  wrote:

> My intended framing of this does not seem to be coming across in my
> arguments.  I am not thinking of this as a way to avoid typing ‘try!’ or
> ‘try?’.  This is not intended to replace any of the current uses of
> ‘throws’.  Rather, it is intended to replace trapping and nil-returning
> functions where converting it to throw would be burdensome in the most
> common use cases, but still desirable in less common use cases.  In my
> mind, it is only enabling the author to provide extra information and
> flexibility, compared to the current behavior.
>
> For example, let’s say I have a failable initializer, which could fail for
> 2 or 3 different reasons, and that the vast majority of use-cases I only
> care whether it succeeded or not (which is why nil-returning was chosen)…
> but there may be a rare case or two where I really would prefer to probe
> deeper (and changing it to a throwing initializer would inhibit the
> majority cases).  Then using ’throws?’ allows the primary usage to remain
> unchanged, while allowing users to opt-in to throwing behavior when desired.
>
> Right now I end up making multiple functions, which are identical except
> for throw vs nil-return, and must now be kept in sync.  I’ll admit it isn’t
> terribly common, but it has come up enough that I think it would still be
> useful.
>

As you say, I think this is a pretty niche use case. When you are in
control of the code, it's trivial to write a second function that wraps the
throwing function, returning an optional value on error. The only thing
you'd need to keep in sync would be the declaration, not the function body,
and that isn't truly onerous on the rare occasion when this is at issue.


> The other argument I will make is one of symmetry.  We have 3 different
> types of error handling in swift: throwing, optional-returns, and trapping.
>

As the Error Handling Rationale document has pointed out, these three
different types of error handling are meant for different _kinds_ of error.
The idea is that ideally the choice of what kind of error handling to use
shouldn't be down to taste or other arbitrary criteria, but should reflect
whether we're dealing with a recoverable error (throws), simple domain
error (return nil), or logical error (trap). That much can be determined at
the point of declaration. At the use site, there are tools to allow the end
user to handle these errors in a variety of ways, but there is a logic
behind allowing conversions between some and not all combinations:

* A logical error is meant to be unrecoverable and thus cannot be converted
to either nil or throw. To call a function that traps is to assert that the
function's preconditions are met. If it's a possibility that the
preconditions cannot be met, it should be handled before calling the
function. A trap represents a programming mistake that should be fixed by
changing the code so as not to trap. There are adequate solutions to the
few instances where an error that currently traps might not be always have
to be fatal: in the case of array indices, for instance, there's been
proposals to allow more lenient subscripting that don't trap, at the cost
of extra overhead--of course, you can already implement this for yourself
in an extension.

* A simple domain error fails in only one obvious way and doesn't need an
error; the end user can always decide that a failure should be handled by
trapping using `!`--in essence, the user is asserting that the occurrence
of a simple domain error at that use site is a logical error. It shouldn't
be useful to convert nil to an error, because a simple domain error should
be able to fail in only one way; if the function fails in more than one
way, the function should throw, as it's no longer a simple domain error.

* A recoverable error can fail in one or more ways, and how you recover may
depend on how it failed; a user can always decide that they'll always
recover in the same way by using `try?`, or they can assert that it's a
logical error to fail at all using `try!`. The choice is up to the user.

As far as I can tell, `throws?` and `throws!` do not change these choices;
it simply says that a recoverable error should be handled by default as a
simple domain error or a logical error, which in the Swift error handling
model should be up to the author who's using the function and not the
author who's declaring it.


> There is already some ability to convert between these:
>
> If you have a throwing function:
> ‘try?’ allows you to convert to optional-return
> ‘try!’ allows you to convert to trapping
>
> If you have an optional-return:
> ‘!’ allows you to convert to trapping
> you are unable to convert to throwing (because it requires extra info
> which isn’t available)
>
> If you have a trapping function, you are unable to convert to either.
>
> With ‘throws?’ you have an optional return which you can convert to
> throwing with ‘try’
>
> With 

Re: [swift-evolution] Throws? and throws!

2017-01-14 Thread Jonathan Hull via swift-evolution
My intended framing of this does not seem to be coming across in my arguments.  
I am not thinking of this as a way to avoid typing ‘try!’ or ‘try?’.  This is 
not intended to replace any of the current uses of ‘throws’.  Rather, it is 
intended to replace trapping and nil-returning functions where converting it to 
throw would be burdensome in the most common use cases, but still desirable in 
less common use cases.  In my mind, it is only enabling the author to provide 
extra information and flexibility, compared to the current behavior.

For example, let’s say I have a failable initializer, which could fail for 2 or 
3 different reasons, and that the vast majority of use-cases I only care 
whether it succeeded or not (which is why nil-returning was chosen)… but there 
may be a rare case or two where I really would prefer to probe deeper (and 
changing it to a throwing initializer would inhibit the majority cases).  Then 
using ’throws?’ allows the primary usage to remain unchanged, while allowing 
users to opt-in to throwing behavior when desired.

Right now I end up making multiple functions, which are identical except for 
throw vs nil-return, and must now be kept in sync.  I’ll admit it isn’t 
terribly common, but it has come up enough that I think it would still be 
useful.


The other argument I will make is one of symmetry.  We have 3 different types 
of error handling in swift: throwing, optional-returns, and trapping.  There is 
already some ability to convert between these:

If you have a throwing function:
‘try?’ allows you to convert to optional-return
‘try!’ allows you to convert to trapping

If you have an optional-return:
‘!’ allows you to convert to trapping
you are unable to convert to throwing (because it requires extra info 
which isn’t available)

If you have a trapping function, you are unable to convert to either.

With ‘throws?’ you have an optional return which you can convert to throwing 
with ‘try’

With ‘throws!’ you have a trapping function where:
‘try?’ allows you to convert to optional-return
‘try’ allows you to convert to throwing


Thus, ‘throws?’ and ‘throws!’ allow you provide optional-return and trapping 
functions where extra information is provided so that it is possible to convert 
to throwing when desired.  In cases where this conversion is not appropriate, 
the author would simply continue to use the current methods.

Basically it is useful in designs where optional-return or trapping were 
ultimately chosen, but there was also a strong case to be made for making it a 
throwing function.  I think the fears of people using it instead of ‘throws’ 
are unfounded because they already have the ability to use optionals or 
trapping… this just mitigates some of the losses from those choices. 

Does that make more sense?  

Thanks,
Jon



> On Jan 12, 2017, at 5:34 PM, Greg Parker  wrote:
> 
> 
>> On Jan 12, 2017, at 4:46 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>>> On Thu, Jan 12, 2017 at 6:27 PM, Jonathan Hull >> > wrote:
>>> 
>>> Also, ‘try’ is still required to explicitly mark a potential error 
>>> propagation point, which is what it was designed to do.  You don’t have 
>>> ‘try’ with the variants because it is by default no longer a propagation 
>>> point (unless you make it one explicitly with ’try’).
>> 
>> If this is quite safe and more convenient, why then shouldn't it be the 
>> behavior for `throws`? (That is, why not just allow people to call throwing 
>> functions without `try` and crash if the error isn't caught? It'd be a 
>> purely additive proposal that's backwards compatible for all currently 
>> compiling code.)
> 
> Swift prefers that potential runtime crash points be visible in the code. You 
> can ignore a thrown error and crash instead, but the code will say `try!`. 
> You can force-unwrap an Optional and crash if it is nil, but the code will 
> say `!`. 
> 
> Allowing `try` to be omitted would obscure those crash points from humans 
> reading the code. It would no longer be possible to read call sites and be 
> able to distinguish which ones might crash due to an uncaught error.
> 
> (There are exceptions to this rule. Ordinary arithmetic and array access are 
> checked at runtime, and the default syntax is one that may crash.)
> 
> 
> -- 
> Greg Parker gpar...@apple.com  Runtime 
> Wrangler
> 
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-13 Thread Karl Wagner via swift-evolution

> On 13 Jan 2017, at 17:10, Joe Groff via swift-evolution 
>  wrote:
> 
> 
>> On Jan 12, 2017, at 2:58 PM, Jonathan Hull via swift-evolution 
>>  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.
>> 
>> 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.  
>> 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.
>> 
>> I think this would really increase the availability of error handling in 
>> areas where it is impractical right now…
>> 
>> Thanks,
>> Jon
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> Another place I can see this being useful is for higher-order functions which 
> "obviously" work on a throwing operation. The most obvious example would be a 
> constructor for a Result type that collects the success or error result from 
> a throwing closure:
> 
> enum Result {
>  case ok(T)
>  case error(Error)
> 
>  init(_ f: () throws -> T) {
>do {
>  self = .ok(try f())
>} catch {
>  self = .error(error)
>}
>  }
> }
> 
> Having to write `Result { try somethingThatMightFail() }` feels a bit silly 
> because "obviously" the operation you pass to Result is going to be able to 
> fail. Such a feature does feel like it could be easy to misuse, though.
> 
> -Joe
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

That works for single-expression closures, but as soon as the closure becomes 
more complex - say, if you want to transform the result of 
somethingThatMightFail() before returning it - it becomes valuable to see the 
point at which the entire operation might fail

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-13 Thread Joe Groff via swift-evolution

> On Jan 12, 2017, at 2:58 PM, Jonathan Hull via swift-evolution 
>  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.
> 
> 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.  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.
> 
> I think this would really increase the availability of error handling in 
> areas where it is impractical right now…
> 
> Thanks,
> Jon
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

Another place I can see this being useful is for higher-order functions which 
"obviously" work on a throwing operation. The most obvious example would be a 
constructor for a Result type that collects the success or error result from a 
throwing closure:

enum Result {
  case ok(T)
  case error(Error)

  init(_ f: () throws -> T) {
do {
  self = .ok(try f())
} catch {
  self = .error(error)
}
  }
}

Having to write `Result { try somethingThatMightFail() }` feels a bit silly 
because "obviously" the operation you pass to Result is going to be able to 
fail. Such a feature does feel like it could be easy to misuse, though.

-Joe
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-13 Thread Karl Wagner via swift-evolution
I can see the appeal, but really throwable errors are just one kind of error 
that can happen in code.

Preconditions are a different thing. They represent axioms that must be kept 
for a sane program. It’s up to the programmer to decide whether something 
should be treated as an axiom or something recoverable. For a few particular 
operations (Array indexing, arithmetic), the standard library designers have 
decided that out-of-bounds values are to be considered axiom violations.

If that’s not convenient for your application, you could suggest changing the 
standard library to include throwing or optional-wrapped alternatives. You 
could also write your own:

extension Array {
subscript(unchecked index: Index) -> Iterator.Element? {   // 
Subscripts aren’t allowed to throw. There’s another proposal on that.
guard (startIndex.. On 12 Jan 2017, at 23:58, Jonathan Hull via swift-evolution 
>  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.
> 
> 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.  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.
> 
> I think this would really increase the availability of error handling in 
> areas where it is impractical right now…
> 
> Thanks,
> Jon
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Rien via swift-evolution
-1

I think the basic type system should remain free of such constructs.

I.e. if a Throws? is necessary on a + operation between integers, then the 
integers should be encapsulated into their own type.

In fact I am thinking lately of the “need” for a new type system in parallel to 
the current type system specifically for arithmetic. It would consist of 
Naturals, Reals, Imaginary etc. These new types would also have Nan and 
Infinite as members and use these to deal with out-of-bounds situations. 
Besides, it should be possible to constrain a subtype of them to a predefined 
ranges etc.

While these are just ‘thoughts’ at the moment, I did come to the conclusion 
that “one size fits all” is not the correct approach.
And I apply the same thinking to the suggested Throws?.
Imo it would introduce side effects into the current type system that would 
only benefit a small subset of users, and it would -probably- not completely 
satisfy those user fully. Hence a new arithmetic based type system would 
probably be better. And until (if ever) such a system is available it would imo 
be better to keep things as they are and implement specific mathematical 
requirements in wrappers.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl




> On 12 Jan 2017, at 23:58, Jonathan Hull via swift-evolution 
>  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.
> 
> 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.  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.
> 
> I think this would really increase the availability of error handling in 
> areas where it is impractical right now…
> 
> Thanks,
> Jon
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Jose Cheyo Jimenez via swift-evolution

> On Jan 12, 2017, at 5:34 PM, Greg Parker via swift-evolution 
>  wrote:
> 
> 
>> On Jan 12, 2017, at 4:46 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>>> On Thu, Jan 12, 2017 at 6:27 PM, Jonathan Hull >> > wrote:
>>> 
>>> Also, ‘try’ is still required to explicitly mark a potential error 
>>> propagation point, which is what it was designed to do.  You don’t have 
>>> ‘try’ with the variants because it is by default no longer a propagation 
>>> point (unless you make it one explicitly with ’try’).
>> 
>> If this is quite safe and more convenient, why then shouldn't it be the 
>> behavior for `throws`? (That is, why not just allow people to call throwing 
>> functions without `try` and crash if the error isn't caught? It'd be a 
>> purely additive proposal that's backwards compatible for all currently 
>> compiling code.)
> 
> Swift prefers that potential runtime crash points be visible in the code. You 
> can ignore a thrown error and crash instead, but the code will say `try!`. 
> You can force-unwrap an Optional and crash if it is nil, but the code will 
> say `!`. 
> 
> Allowing `try` to be omitted would obscure those crash points from humans 
> reading the code. It would no longer be possible to read call sites and be 
> able to distinguish which ones might crash due to an uncaught error.
> 
> (There are exceptions to this rule. Ordinary arithmetic and array access are 
> checked at runtime, and the default syntax is one that may crash.)
> 

Indirectly Diving by zero [1] // the compiler won’t let you directly divide by 
zero
Overflow or underflow [2]
Array Index out of range

Aside from those, Are there any other runtime “exceptions"?


[1] https://en.wikipedia.org/wiki/Undefined_(mathematics)#In_arithmetic 


//[2] example:
let number = Int16.max
print(number+1) //crash Illegal instruction

> 
> -- 
> Greg Parker gpar...@apple.com  Runtime 
> Wrangler
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 12, 2017 at 7:34 PM, Greg Parker  wrote:

>
> On Jan 12, 2017, at 4:46 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Thu, Jan 12, 2017 at 6:27 PM, Jonathan Hull  wrote:
>
>
> Also, ‘try’ is still required to explicitly mark a potential error
> propagation point, which is what it was designed to do.  You don’t have
> ‘try’ with the variants because it is by default no longer a propagation
> point (unless you make it one explicitly with ’try’).
>
>
> If this is quite safe and more convenient, why then shouldn't it be the
> behavior for `throws`? (That is, why not just allow people to call throwing
> functions without `try` and crash if the error isn't caught? It'd be a
> purely additive proposal that's backwards compatible for all currently
> compiling code.)
>
>
> Swift prefers that potential runtime crash points be visible in the code.
> You can ignore a thrown error and crash instead, but the code will say
> `try!`. You can force-unwrap an Optional and crash if it is nil, but the
> code will say `!`.
>
> Allowing `try` to be omitted would obscure those crash points from humans
> reading the code. It would no longer be possible to read call sites and be
> able to distinguish which ones might crash due to an uncaught error.
>
> (There are exceptions to this rule. Ordinary arithmetic and array access
> are checked at runtime, and the default syntax is one that may crash.)
>

FWIW, that was meant to be an argument a fortiori (well, ad absurdum, I
suppose). If `throws!` is a good idea (whose purpose is to permit omission
of `try!` at call sites), then how much nicer would it be if we could just
do that with `throws`. It is, after all, technically source compatible. But
it is not, I agree, such a good idea with `throws`, so I'm skeptical of its
worth with the increased burden of new syntax.


-- 
> Greg Parker gpar...@apple.com Runtime Wrangler
>
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Greg Parker via swift-evolution

> On Jan 12, 2017, at 4:46 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
>> On Thu, Jan 12, 2017 at 6:27 PM, Jonathan Hull > > wrote:
>> 
>> Also, ‘try’ is still required to explicitly mark a potential error 
>> propagation point, which is what it was designed to do.  You don’t have 
>> ‘try’ with the variants because it is by default no longer a propagation 
>> point (unless you make it one explicitly with ’try’).
> 
> If this is quite safe and more convenient, why then shouldn't it be the 
> behavior for `throws`? (That is, why not just allow people to call throwing 
> functions without `try` and crash if the error isn't caught? It'd be a purely 
> additive proposal that's backwards compatible for all currently compiling 
> code.)

Swift prefers that potential runtime crash points be visible in the code. You 
can ignore a thrown error and crash instead, but the code will say `try!`. You 
can force-unwrap an Optional and crash if it is nil, but the code will say `!`. 

Allowing `try` to be omitted would obscure those crash points from humans 
reading the code. It would no longer be possible to read call sites and be able 
to distinguish which ones might crash due to an uncaught error.

(There are exceptions to this rule. Ordinary arithmetic and array access are 
checked at runtime, and the default syntax is one that may crash.)


-- 
Greg Parker gpar...@apple.com  Runtime 
Wrangler


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 12, 2017 at 6:17 PM, Jonathan Hull  wrote:

>
> On Jan 12, 2017, at 3:35 PM, Xiaodi Wu  wrote:
>
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution <
> swift-evolution@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.
>
>
> 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!’.
>
> 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 should add, with respect to this point: I highly agree that "high
probability of foot-gunning" is one criterion for caution. But I think
there are other valid reasons for caution, and one has been perhaps only
occasionally remarked upon on this list:

One discussion--I can't recall whether on this list or on
swift-users--showed that there was already some confusion about best
practices surrounding failable vs throwing functions; those who raised the
point argued that two ways of failing was one too many. The Error Handling
Rationale document makes a very good case for each holding its own weight,
but I think we can all see that the choice does add to the complexity 

Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 12, 2017 at 6:27 PM, Jonathan Hull  wrote:

> The problem with Java (and ObjC) is that exceptions can propagate
> unexpectedly into scopes which they weren’t expected and you end up with
> objects in inconsistent states where it is nearly impossible to continue in
> any meaningful way.  That can’t happen here as the error will never
> propagate beyond where it is expected to be.  On the contrary, ‘throws!’
> and ‘throws?’ both stop the propagation earlier than ‘throws’.
>

That's a fair point about `throws!`.

It seems that your motivation for `throws!` is to avoid writing `try!` at
the call site, since the functionality is otherwise the same. That keyword,
notably, is required at most once per statement. So--unless you're trying
to build up a solution for a whole new category of error (as mentioned
above)--the question boils down to: does having to write `try!` offer four
letters' worth of benefit at the call site? Your answer, if I understand,
seems to be: sometimes it might not be worth four letters, and that should
be enough to justify a new feature. I think, to make a convincing case,
you'll have to offer real-world use cases where many can agree on that
point, sufficient to justify the engineering resources for such a feature.
IMO the mere possibility that such a use case may exist is not enough,
especially offset against what I would argue is a real benefit to readers
of code that every call to a throwing function is currently clearly
annotated.

As to `throws?`, I'm not sure quite sure how it is supposed to work. If a
function `throws? -> Int`, is the return value actually of type `Int?`? And
if it's `throws? -> Int?`, then is the return value actually of type
`Int??`? In what ways would this design be superior to the already sketched
out `Result` type outlined in the Error Handling Rationale document,
which several people on this list have lined up to propose? Would a
`Result` cover even your use cases for `throws!`?

Also, ‘try’ is still required to explicitly mark a potential error
> propagation point, which is what it was designed to do.  You don’t have
> ‘try’ with the variants because it is by default no longer a propagation
> point (unless you make it one explicitly with ’try’).
>

If this is quite safe and more convenient, why then shouldn't it be the
behavior for `throws`? (That is, why not just allow people to call throwing
functions without `try` and crash if the error isn't caught? It'd be a
purely additive proposal that's backwards compatible for all currently
compiling code.)

Thanks,
> Jon
>
> On Jan 12, 2017, at 3:50 PM, Xiaodi Wu  wrote:
>
> Some additional thoughts: if I recall correctly from my (limited) Java
> days, throwing in Java worked essentially like your proposed `throws!`.
> That the Swift model expressly deviates from that example was not by
> accident, as far as I can tell. According to the error handling docs in the
> Swift repo:
>
> "Once an error is thrown, Swift will automatically propagate it out of
> scopes (that permit it), rather than relying on the programmer to manually
> check for errors and do their own control flow. This is just a lot less
> boilerplate for common error handling tasks. However, doing this naively
> would introduce a lot of implicit control flow, which makes it difficult to
> reason about the function's behavior. This is a serious maintenance problem
> and has traditionally been a considerable source of bugs in languages that
> heavily use exceptions.
>
> "Therefore, while Swift automatically propagates errors, it requires that
> statements and expressions that can implicitly throw be marked with the
> `try` keyword."
>
> So I think what this is saying is that requiring `try` _every time_ is
> core to the design of Swift error handling, and that `throws!` or even
> `throws?` would undo it.
>
>
> On Thu, Jan 12, 2017 at 5:35 PM, Xiaodi Wu  wrote:
>
>> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution <
>> swift-evolution@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 

Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 12, 2017 at 6:17 PM, Jonathan Hull  wrote:

>
> On Jan 12, 2017, at 3:35 PM, Xiaodi Wu  wrote:
>
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution <
> swift-evolution@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 

Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Jonathan Hull via swift-evolution
The problem with Java (and ObjC) is that exceptions can propagate unexpectedly 
into scopes which they weren’t expected and you end up with objects in 
inconsistent states where it is nearly impossible to continue in any meaningful 
way.  That can’t happen here as the error will never propagate beyond where it 
is expected to be.  On the contrary, ‘throws!’ and ‘throws?’ both stop the 
propagation earlier than ‘throws’.

Also, ‘try’ is still required to explicitly mark a potential error propagation 
point, which is what it was designed to do.  You don’t have ‘try’ with the 
variants because it is by default no longer a propagation point (unless you 
make it one explicitly with ’try’).

Thanks,
Jon

> On Jan 12, 2017, at 3:50 PM, Xiaodi Wu  wrote:
> 
> Some additional thoughts: if I recall correctly from my (limited) Java days, 
> throwing in Java worked essentially like your proposed `throws!`. That the 
> Swift model expressly deviates from that example was not by accident, as far 
> as I can tell. According to the error handling docs in the Swift repo:
> 
> "Once an error is thrown, Swift will automatically propagate it out of scopes 
> (that permit it), rather than relying on the programmer to manually check for 
> errors and do their own control flow. This is just a lot less boilerplate for 
> common error handling tasks. However, doing this naively would introduce a 
> lot of implicit control flow, which makes it difficult to reason about the 
> function's behavior. This is a serious maintenance problem and has 
> traditionally been a considerable source of bugs in languages that heavily 
> use exceptions.
> 
> "Therefore, while Swift automatically propagates errors, it requires that 
> statements and expressions that can implicitly throw be marked with the `try` 
> keyword."
> 
> So I think what this is saying is that requiring `try` _every time_ is core 
> to the design of Swift error handling, and that `throws!` or even `throws?` 
> would undo it.
> 
> 
> On Thu, Jan 12, 2017 at 5:35 PM, Xiaodi Wu  > wrote:
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution 
> > 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 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.
> 
> 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 

Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Kevin Nattinger via swift-evolution

> On Jan 12, 2017, at 3:50 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Some additional thoughts: if I recall correctly from my (limited) Java days, 
> throwing in Java worked essentially like your proposed `throws!`. That the 
> Swift model expressly deviates from that example was not by accident, as far 
> as I can tell. According to the error handling docs in the Swift repo:

Java (functionally) has two types of exceptions, checked and unchecked. 
Checked exceptions must either be caught and handled or the calling method must 
be declared as throwing the same exception (or an ancestor).
Unchecked exceptions do not need to be declared, and can either be caught or 
implicitly work their way back up the stack until either they’re caught or they 
hit the top of the stack (in which case the JRE kills the program.

Objective-C’s exception system is essentially Java’s unchecked type, and 
Swift’s is checked (with the addition of requiring `try` at the call site. At 
risk of getting off on a tangent, I really dislike the raw `try` requirement. 
`try?` and `try!` at least make sense as they specify how to handle the 
exception; `try` does not.)
Swift’s exception system is basically checked exceptions; Objective-C’s is 
unchecked.

As far as I can tell, this proposal isn’t really like either; `throws?` would 
swallow the exception entirely if the caller didn’t handle it and `throws!` 
would kill the app without giving higher stack frames a chance to catch it. I’m 
really not a fan of either; I’d much prefer unchecked exceptions, and I think 
they fulfill the OP’s underlying concerns.

> 
> "Once an error is thrown, Swift will automatically propagate it out of scopes 
> (that permit it), rather than relying on the programmer to manually check for 
> errors and do their own control flow. This is just a lot less boilerplate for 
> common error handling tasks. However, doing this naively would introduce a 
> lot of implicit control flow, which makes it difficult to reason about the 
> function's behavior. This is a serious maintenance problem and has 
> traditionally been a considerable source of bugs in languages that heavily 
> use exceptions.
> 
> "Therefore, while Swift automatically propagates errors, it requires that 
> statements and expressions that can implicitly throw be marked with the `try` 
> keyword."
> 
> So I think what this is saying is that requiring `try` _every time_ is core 
> to the design of Swift error handling, and that `throws!` or even `throws?` 
> would undo it.
> 
> 
> On Thu, Jan 12, 2017 at 5:35 PM, Xiaodi Wu  > wrote:
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution 
> > 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 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 

Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Jonathan Hull via swift-evolution

> On Jan 12, 2017, at 3:35 PM, Xiaodi Wu  wrote:
> 
> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution 
> > 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.


> 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!’.

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.


> 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 

Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Xiaodi Wu via swift-evolution
Some additional thoughts: if I recall correctly from my (limited) Java
days, throwing in Java worked essentially like your proposed `throws!`.
That the Swift model expressly deviates from that example was not by
accident, as far as I can tell. According to the error handling docs in the
Swift repo:

"Once an error is thrown, Swift will automatically propagate it out of
scopes (that permit it), rather than relying on the programmer to manually
check for errors and do their own control flow. This is just a lot less
boilerplate for common error handling tasks. However, doing this naively
would introduce a lot of implicit control flow, which makes it difficult to
reason about the function's behavior. This is a serious maintenance problem
and has traditionally been a considerable source of bugs in languages that
heavily use exceptions.

"Therefore, while Swift automatically propagates errors, it requires that
statements and expressions that can implicitly throw be marked with the
`try` keyword."

So I think what this is saying is that requiring `try` _every time_ is core
to the design of Swift error handling, and that `throws!` or even `throws?`
would undo it.


On Thu, Jan 12, 2017 at 5:35 PM, Xiaodi Wu  wrote:

> On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution <
> swift-evolution@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 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.
>
> 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.
>
> 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

Re: [swift-evolution] Throws? and throws!

2017-01-12 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 12, 2017 at 4:58 PM, Jonathan Hull via swift-evolution <
swift-evolution@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 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.

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.

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@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution