[swift-evolution] [Pitch] Introducing the "Unwrap or Die" operator to the standard library

Xiaodi Wu xiaodi.wu at gmail.com
Wed Jun 28 22:49:54 CDT 2017


On Wed, Jun 28, 2017 at 10:33 PM, Paul Cantrell <cantrell at pobox.com> wrote:

>
> On Jun 28, 2017, at 9:50 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Wed, Jun 28, 2017 at 8:54 PM, Paul Cantrell <paul at bustoutsolutions.com>
> wrote:
>
>>
>> On Jun 28, 2017, at 8:32 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>> I would like to see an example where this string plausibly makes the
>> difference between having to hunt down the code and not have to do so. I do
>> not believe that "array must not be empty" or "array guaranteed non-empty"
>> is such an example, and I cannot myself imagine another scenario where it
>> would make such a difference.
>>
>>
>> You needn’t imagine. There was one up-thread:
>>
>>   let paramData = params.data(using: String.Encoding.ascii)!
>>
>> Huh? Why is force unwrap safe here? OK, the code plainly says the author
>> thinks that `params` must already be ASCII, but why is that a safe
>> assumption? What reasoning lead to that? What other sections of the code
>> does that reasoning depend on? If we get a crash on this line of code, what
>> chain of assumptions should we follow to discover the change that broke the
>> original author’s reasoning behind the force unwrap?
>>
>> This is a job for a comment:
>>
>>   let paramData = params.data(using: String.Encoding.ascii)!  // params
>>  is URL-escaped, thus already ASCII
>>
>> Aha, it’s URL escaped.
>>
>> That comment does not repeat information already stated in the code
>> itself. It does what any good comment does: it explains intent, context,
>> and rationale. It doesn’t restate _what_, but rather explains _why_.
>>
>> For those who appreciate comments like that, this proposal simply allows
>> them to surface at runtime:
>>
>>   let paramData = params.data(using: String.Encoding.ascii) !! "params
>>  is URL-escaped, thus already ASCII"
>>
>> And those who see no value in such a runtime message — and thus likely
>> also see no value such a comment — are free not to use either.
>>
>
> If this is the most convincing example, then I'd actually be adamantly
> _against_ such an operator (where now I'm merely skeptical and would like
> to see evidence of usefulness). This example is, quite simply, _wrong_.
> Here's why:
>
> First, if force unwrapping fails, the message should explain why it
> failed: the reason why it failed is _not_ because it's URL-escaped and
> _not_ because it's ASCII, but rather because it's **not** ASCII.
>
>
> Fine, then:
>
>     let paramData = params.data(using: String.Encoding.ascii) !!
> “params must be URL-escaped, and thus ASCII"
>
> …or format the runtime message to fit that style of phrasing:
>
>     fatal error: unexpectedly found nil while unwrapping an Optional value
>     Failing underlying assumption:
>         params is URL-escaped, thus already ASCII
>     Current stack trace:
>>
> Second, even supposing the wording were fixed, it's at best not more
> useful than `!` and at worst misleading.
>
>>
> If the error message is "params not URL-escaped," then it's misleading, as
> that's not at all what the LHS is actually asserting: it can be unwrapped
> *whether or not* it's URL-escaped and it only matters that it's ASCII.
>
>
> Yes, of _course_ it’s not what the LHS is actually asserting. That is
> precisely the point of having a message. There is pertinent information not
> already present in the code.
>

See below.


> The message describes an invariant not captured by the type system. In
> other words, the author of this code believes they have guaranteed
> something that the compiler itself cannot check. Thus this statement is
> exactly backwards:
>
> You **absolutely cannot** proceed from this point in the code assuming
> that `paramData` is a URL-escaped string.
>
>
> The author of this code is telling you they have _already_ proceeded from
> this point assuming that `paramData` is URL-escaped.
>

No, the author proceeded from a previous point assuming that `params` is
URL-escaped. The act of unwrapping does not demarcate the transition
between where `params` is assumed to be URL-escaped and where it is not.
Execution can proceed past this point even if `params` is *not* URL-escaped.

They may have assumed wrong, but even if they did, this insight into the
> developer’s thinking is valuable.
>
> Indeed, though we try to minimize it, there will inevitably be code that
> relies on assumptions the compiler cannot check. That is why the language
> has ! in the first place. Those uncheckable assumptions are not always
> self-evident. This is why languages provide comments and diagnostic
> messages.
>
> Literalism nit-picking over the semantics of the RHS deliberately miss the
> original argument: the RHS is information-bearing.
>

_Of course_ the goal is to nail down the semantics of the RHS. It's a
proposal for an infix operator, for which the semantics of the LHS are not
in dispute. What else is there to talk about?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170628/daa598ef/attachment.html>


More information about the swift-evolution mailing list