<div dir="ltr">On Tue, Jan 17, 2017 at 6:50 PM, Jonathan Hull <span dir="ltr"><<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word">I rewrote some code which used NSDecimalNumber to use Decimal and it went from 20 lines of hard to follow code to 2 lines of easy to follow expressions. ‘2+2’ is much easier to understand at a glance than having a sentence for each operation.</div></blockquote><div><br></div><div>So, again, your particular problem isn't about whether Swift lets you handle errors in a certain way--it already does. Your objection is about the spelling.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div>Also the control flow is completely different. With one, you have try and then a full equation, and you catch and handle different cases if something went wrong (overflow, underflow, divide by zero). With the other you have to have a guard AFTER each line which uses a previous result (or a pyramid of doom), potentially repeating the same error handling code over and over:</div></div></blockquote><div><br></div><div>You already have the option of making this work for you _exactly_ as you like:</div><div><br></div><div>```</div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">enum</span><span style="font-variant-ligatures:no-common-ligatures"> ArithmeticError : </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Error</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">case</span><span style="font-variant-ligatures:no-common-ligatures"> add, multiply, subtract, divide</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">}</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">infix</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">operator</span><span style="font-variant-ligatures:no-common-ligatures"> &&+ : AdditionPrecedence</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">infix</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">operator</span><span style="font-variant-ligatures:no-common-ligatures"> &&- : AdditionPrecedence</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">infix</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">operator</span><span style="font-variant-ligatures:no-common-ligatures"> &&* : MultiplicationPrecedence</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">infix</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">operator</span><span style="font-variant-ligatures:no-common-ligatures"> &&/ : MultiplicationPrecedence</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(186,45,162)"><span style="font-variant-ligatures:no-common-ligatures">extension</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)"> {</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">static</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> &&+ (lhs: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures">, rhs: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures">) </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">throws</span><span style="font-variant-ligatures:no-common-ligatures"> -> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> (result, flag) = </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures">.</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(62,30,129)">addWithOverflow</span><span style="font-variant-ligatures:no-common-ligatures">(lhs, rhs)</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">guard</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(62,30,129)">!</span><span style="font-variant-ligatures:no-common-ligatures">flag </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">else</span><span style="font-variant-ligatures:no-common-ligatures"> { </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">throw</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(79,129,135)">ArithmeticError</span><span style="font-variant-ligatures:no-common-ligatures">.</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(49,89,93)">add</span><span style="font-variant-ligatures:no-common-ligatures"> }</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">return</span><span style="font-variant-ligatures:no-common-ligatures"> result</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures"> }</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">}</span></p></div><div>```</div><div><br></div><div>This requires absolutely no redesign of Swift error handling. You can even customize how fine-grained the error messages are.</div><div><br></div><div>By contrast, I think the present topic of this thread--identifying ways in which a logic error might bring down only a single process, or whether that's even a desirable thing--is a sorely needed discussion which will require deep support baked into the compiler.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>let (a,o1) = Int.addWithOverflow(x,y)</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>guard o1 == false else {throw MyError}</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>let (b,o2) = Int.multiplyWithOverflow(a,z)</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>guard o2 == false else {throw MyError}</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>let (c,o3) = Int.subtractWithOverflow(b,z)</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>guard o3 == false else {throw MyError}</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>return c</div><div><br></div><div>vs:</div><div><br></div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>do{</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span> return try ((x+y)*z)-z</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>}catch _ {</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span> throw MyError</div><div><span class="gmail-m_-3335266657461987228Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div><br></div><div><br></div><div>Thanks,</div><div>Jon<div><div class="gmail-h5"><br><div><br></div><div><br><div><blockquote type="cite"><div>On Jan 17, 2017, at 4:22 PM, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="gmail-m_-3335266657461987228Apple-interchange-newline"><div>We already have three ways of handling integer overflow:<br><br>+ traps<br>&+ overflows<br>addWithOverflow overflows and sets a flag if it does so<br><br>This supports all possible ways of handling the issue: you can trap, you can get a result and not care about the overflow flag, or you can get the result *and* the overflow flag. You can even discard the result and work with only the flag.<br><br>I don't see how this doesn't meet exactly what you and Jonathan Hull describe: it is opt-in, optional for callers, and does not propagate. It doesn't require try or any other cumbersome syntax, and it allows you to just compute the operation first and handle the overflow later only if it occurs.<br><br>For array indexing, there is an outstanding proposal for more lenient subscripts. In the meantime, you can trivially implement your own. Such a facility would also behave according to your stated requirements.<br><br><div class="gmail_quote"><div dir="ltr">On Tue, Jan 17, 2017 at 18:03 David Waite via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class="gmail-m_-3335266657461987228gmail_msg"><div class="gmail-m_-3335266657461987228gmail_msg"><blockquote type="cite" class="gmail-m_-3335266657461987228gmail_msg"><div class="gmail-m_-3335266657461987228gmail_msg">On Jan 17, 2017, at 1:38 PM, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="gmail-m_-3335266657461987228gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="gmail-m_-3335266657461987228m_-1010993449595040349Apple-interchange-newline gmail-m_-3335266657461987228gmail_msg"><div class="gmail-m_-3335266657461987228gmail_msg"><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="gmail-m_-3335266657461987228gmail_msg">It also means, from a purely pragmatic view, that control flow for</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail-m_-3335266657461987228gmail_msg"><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="gmail-m_-3335266657461987228gmail_msg">things that are really not reliably recoverable conditions (like index</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail-m_-3335266657461987228gmail_msg"><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="gmail-m_-3335266657461987228gmail_msg">out-of-range) is not cleanly separated from control flow for handling</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail-m_-3335266657461987228gmail_msg"><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="gmail-m_-3335266657461987228gmail_msg">recoverable things like dropped network conditions, so it can be really</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail-m_-3335266657461987228gmail_msg"><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="gmail-m_-3335266657461987228gmail_msg">hard to know that you're reliably shutting down the program when you</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail-m_-3335266657461987228gmail_msg"><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="gmail-m_-3335266657461987228gmail_msg">should, and that's not being subverted by some general “recovery” code.</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail-m_-3335266657461987228gmail_msg"></div></blockquote><div class="gmail-m_-3335266657461987228gmail_msg"><br class="gmail-m_-3335266657461987228gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail-m_-3335266657461987228gmail_msg"><div class="gmail-m_-3335266657461987228gmail_msg">Agreed. The “try” syntax is part of a decision to use errors to represent conditions recoverable by business logic. This might be a network connection closed, but shouldn’t be used for conditions like memory allocation failed, a KILL signal, or detection of corrupted data within an application bundle.</div><div class="gmail-m_-3335266657461987228gmail_msg"><br class="gmail-m_-3335266657461987228gmail_msg"></div><div class="gmail-m_-3335266657461987228gmail_msg">In the middle are avoidable runtime errors like array indexing out-of-bounds and math overflow. Some business logic might care about these, in particular logic which deals with arbitrary user input. However, using ‘try’ syntax would result in both an explosion of needing to specify try in expressions, and in errors which can’t really be recovered in typical business logic.</div><div class="gmail-m_-3335266657461987228gmail_msg"><br class="gmail-m_-3335266657461987228gmail_msg"></div><div class="gmail-m_-3335266657461987228gmail_msg">I see this as three regions of error conditions - system level errors that the developer isn’t expected to try and recover from, application-level errors that the developer is likely going to want to control the behavior of, and in between the runtime errors which some logic might care about, but which in most cases should be treated as a system level error.</div><div class="gmail-m_-3335266657461987228gmail_msg"><br class="gmail-m_-3335266657461987228gmail_msg"></div><div class="gmail-m_-3335266657461987228gmail_msg">Java roughly has Error, Exception, and RuntimeException to correspond to these, with a few differences which I generally consider to be flaws in the Java language (RuntimeException is under Exception, RuntimeExceptions percolate up the entire stack rather than being escalated to Errors if unhandled).</div><div class="gmail-m_-3335266657461987228gmail_msg"><br class="gmail-m_-3335266657461987228gmail_msg"></div><div class="gmail-m_-3335266657461987228gmail_msg">I can envision a future state where:</div><div class="gmail-m_-3335266657461987228gmail_msg">- system level errors can have atexit/terminate-style shutdown hooks. These do not support recovery, but can be used to attempt a cleaner shutdown</div><div class="gmail-m_-3335266657461987228gmail_msg">- functions which emit runtime errors (such as math overflow) can support a call form which returns an error rather than precondition failure, but it is opt in and optional for callers. The runtime errors do not propagate automatically, and callers which do not request it get precondition failures</div><div class="gmail-m_-3335266657461987228gmail_msg">- the possibility of containerization so that runtime errors and certain system level errors terminate a thread/actor/app domain rather than the whole process</div></div><div style="word-wrap:break-word" class="gmail-m_-3335266657461987228gmail_msg"><br class="gmail-m_-3335266657461987228gmail_msg"><div class="gmail-m_-3335266657461987228gmail_msg">-DW</div></div>______________________________<wbr>_________________<br class="gmail-m_-3335266657461987228gmail_msg">
swift-evolution mailing list<br class="gmail-m_-3335266657461987228gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail-m_-3335266657461987228gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail-m_-3335266657461987228gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail-m_-3335266657461987228gmail_msg" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br class="gmail-m_-3335266657461987228gmail_msg">
</blockquote></div>
______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></div></blockquote></div><br></div></div></div></div></div></blockquote></div><br></div></div>