[swift-evolution] [Last second] Precedence of nil-coalescing operator seems too low

Pyry Jahkola pyry.jahkola at iki.fi
Thu Sep 8 04:08:00 CDT 2016


To stay slightly on topic of the original Subject line, I'd point out that no one has yet demonstrated an example where the current precedence position of `??` causes bugs at runtime.

The original motivation by Erica simply failed to compile without the parentheses, so it wasn't about confusion so much as about mere convenience. And there exist actual uses where the current precedence brings greater convenience, e.g. when the RHS expression contains arithmetic operations.

Like Wux, I also don't think we have any reason to adjust the precedence of `??` from what it is.

* * *

But then, I also think we should do something to our bitwise ops:

> On 08 Sep 2016, at 09:58, Xiaodi Wu via swift-evolution <swift-evolution at swift.org> wrote:
> 
> You and I seem to agree that `let i = 4 << 1 + 3` is rather reasonable.

Here, I would actually differ somewhat. If there's something that ought to be higher in precedence than `+` and `*`, IMO that would be actual exponentiation, which could be approximated in a math library by the presently missing `**` operator, for example.

> I am not sure how one can make an unintended error either reading or writing this line of code[*].
> 
> [*] Actually, I can see precisely one way to make such an unintended error, since I have actually done so. It has to do with Swift having moved away from the classical C-family operator precedence table. I would actually not be opposed to making changes that guard against such an error.

There's a fair amount of C code out in the wild that is going to be migrated into Swift in the near future. And that code would benefit if Swift's precedence rules didn't unexpectedly break from C – that is, not without the programmer's awareness.

The key differences to C that I think will cause confusion in Swift are:

A) Unlike C, Swift defines `<<` and `>>` with the highest precedence.
B) Unlike C, Swift defines `&` at multiplication precedence (`*` etc.).
C) Unlike C, Swift defines both `^` and `|` at equal precedence to each other, and that is the precedence of addition (`+` etc.).

Other than that, we also use equal precedence for all comparison operators but at the same time remove their associativity, so that can't cause runtime problems (as such code would fail to compile). Here's a full table, with the notable differences marked with a red comment:

Infix operators in C
In Swift 3
// skipping unary ops etc

*  /  %
             <<  >>       // (!)
+  -
      *  &*  /  %  &      // (!)
<<  >>
     +  &+  -  &-  |  ^   // (!)
<  <=  >  >=
...  ..<
==  !=
as  as?  is
&
??
^
<  <=  >  >=  ==  !=  ===  !==  ~=
|
&&
&&
||
||
(default precedence diverges here)
?:
?:
=  @= // for various `@`
=  @= // for various `@`
,
->

I think Jacob has a point in separating bitwise operations into their own hierarchy. I'd recommend doing so all the way, but retaining `&` with a higher "bitwise-multiplicative" precedence:

1) Move `|` and `^` into their own parallel precedence groups named BitwiseOr and BitwiseXor, just above RangeFormation.
2) Move `&` into its own group BitwiseAnd, just above both BitwiseOr and BitwiseXor.
3) Move BitwiseShift (i.e. `<<` and `>>`) just above BitwiseAnd.

That would make it so that rarely occurring*) expressions mixing `^` and `|` would now need parenthesising, but either of them would work together with `&`, `<<`, and `>>` just like they do in C (and just the way binary addition relates to multiplication in the conventions of mathematics).

*) E.g. none found in https://graphics.stanford.edu/~seander/bithacks.html <https://graphics.stanford.edu/~seander/bithacks.html>.

Also integer arithmetic would stay clearly separated from bitwise operations, which in my experience is the source of most bugs and confusion. E.g. the expressions `a & b + c`, `a | b + c`, and `a << b - c` all compile in both C and Swift, but are parsed in exactly opposing ways.

The whole hierarchy I'm proposing is illustrated in the attachment below, with all changes found in the top part above RangeFormation.

— Pyry



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160908/b43bc6f8/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Swift Precedence Groups.png
Type: image/png
Size: 96944 bytes
Desc: not available
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160908/b43bc6f8/attachment.png>


More information about the swift-evolution mailing list