<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote>That sounds pretty good to me, actually. It removes one category of real-world bugs without fundamentally upending Swift operators. Neat solution regarding separation of | and ^.<br><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><div class="gmail_quote"><div dir="ltr">On Thu, Sep 8, 2016 at 04:08 Pyry Jahkola &lt;<a href="mailto:pyry.jahkola@iki.fi" target="_blank">pyry.jahkola@iki.fi</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>To stay slightly on topic of the original Subject line, I&#39;d point out that no one has yet demonstrated an example where the current precedence position of `??` causes bugs at runtime.</div><div><br></div><div>The original motivation by Erica simply failed to compile without the parentheses, so it wasn&#39;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.</div><div><br></div><div>Like Wux, I also don&#39;t think we have any reason to adjust the precedence of `??` from what it is.</div><div><br></div><div>* * *</div><div><br></div><div>But then, I also think we should do something to our bitwise ops:</div><div><br></div><div></div></div><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On 08 Sep 2016, at 09:58, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div style="font-family:Helvetica;font-size:13px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-size:12.8px">You and I seem to agree that `</span><span style="font-size:12.8px">let i = 4 &lt;&lt; 1 + 3` is rather reasonable.</span></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>Here, I would actually differ somewhat. If there&#39;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.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="font-family:Helvetica;font-size:13px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-size:12.8px">I am not sure how one can make an unintended error either reading or writing this line of code[*].</span></div><div style="font-family:Helvetica;font-size:13px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-size:12.8px"><br></span></div><div style="font-family:Helvetica;font-size:13px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-size:12.8px">[*] 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.</span></div></div></blockquote></div></div><div style="word-wrap:break-word"><div></div><br>

There&#39;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&#39;s precedence rules didn&#39;t unexpectedly break from C – that is, not without the programmer&#39;s awareness.<div><br></div><div>The key differences to C that I think will cause confusion in Swift are:</div><div><br></div><div>A) Unlike C, Swift defines `&lt;&lt;` and `&gt;&gt;` with the highest precedence.</div><div>B) Unlike C, Swift defines `&amp;` at multiplication precedence (`*` etc.).</div><div>C) Unlike C, Swift defines both `^` and `|` at equal precedence to each other, and that is the precedence of addition (`+` etc.).</div><div><div><br></div><div>Other than that, we also use equal precedence for all comparison operators but at the same time remove their associativity, so that can&#39;t cause runtime problems (as such code would fail to compile). Here&#39;s a full table, with the notable differences marked with a red comment:</div></div><div><br></div><div><table cellspacing="0" cellpadding="0" style="border-collapse:collapse">
<tbody>
<tr>
<td valign="top" style="width:150.0px;height:11.0px;background-color:#bec0bf;border-style:solid;border-width:1.0px 1.0px 1.0px 1.0px;border-color:#000000 #000000 #000000 #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo"><b>Infix operators in C</b></font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;background-color:#bec0bf;border-style:solid;border-width:1.0px 1.0px 1.0px 1.0px;border-color:#000000 #000000 #000000 #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo"><b>In Swift 3</b></font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:10.0px;border-style:solid;border-width:1.0px 0.0px 0.0px 1.0px;border-color:#000000 transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#7f7f7f" style="font-size:10px;line-height:normal;font-family:Menlo;color:rgb(127,127,127)">// skipping unary ops etc</font></div>
</td>
<td valign="top" style="width:241.0px;height:10.0px;border-style:solid;border-width:1.0px 1.0px 0.0px 0.0px;border-color:#000000 #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;font-size:12px;line-height:normal;min-height:14px"><br></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">*  /  %</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#cf232b" style="font-size:10px;line-height:normal;font-family:Menlo;color:rgb(207,35,43)"><b>             &lt;&lt;  &gt;&gt;       // (!)</b></font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">+  -</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">      *  &amp;*  /  %  </font><font face="Menlo" color="#cf232b" style="font-size:10px;line-height:normal;font-family:Menlo;color:rgb(207,35,43)"><b>&amp;      // (!)</b></font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">&lt;&lt;  &gt;&gt;</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">     +  &amp;+  -  &amp;-  </font><font face="Menlo" color="#cf232b" style="font-size:10px;line-height:normal;font-family:Menlo;color:rgb(207,35,43)"><b>|  ^   // (!)</b></font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">&lt;  &lt;=  &gt;  &gt;=</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">...  ..&lt;</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">==  !=</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">as  as?  is</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">&amp;</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">??</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">^</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">&lt;  &lt;=  &gt;  &gt;=  ==  !=  ===  !==  ~=</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">|</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">&amp;&amp;</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">&amp;&amp;</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">||</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">||</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#7f7f7f" style="font-size:10px;line-height:normal;font-family:Menlo;color:rgb(127,127,127)">(default precedence diverges here)</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">?:</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">?:</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 0.0px 1.0px;border-color:transparent transparent transparent #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">=  @= </font><font face="Menlo" color="#7f7f7f" style="font-size:10px;line-height:normal;font-family:Menlo;color:rgb(127,127,127)">// for various `@`</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 0.0px 0.0px;border-color:transparent #000000 transparent transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">=  @= </font><font face="Menlo" color="#7f7f7f" style="font-size:10px;line-height:normal;font-family:Menlo;color:rgb(127,127,127)">// for various `@`</font></div>
</td>
</tr>
<tr>
<td valign="top" style="width:151.0px;height:11.0px;border-style:solid;border-width:0.0px 0.0px 1.0px 1.0px;border-color:transparent transparent #000000 #000000;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">,</font></div>
</td>
<td valign="top" style="width:241.0px;height:11.0px;border-style:solid;border-width:0.0px 1.0px 1.0px 0.0px;border-color:transparent #000000 #000000 transparent;padding:4.0px 4.0px 4.0px 4.0px"><div style="margin:0px;text-align:center"><font face="Menlo" color="#000000" style="font-size:10px;line-height:normal;font-family:Menlo">-&gt;</font></div>
</td>
</tr>
</tbody>
</table></div><div><br></div><div>I think Jacob has a point in separating bitwise operations into their own hierarchy. I&#39;d recommend doing so all the way, but retaining `&amp;` with a higher &quot;bitwise-multiplicative&quot; precedence:</div><div><br></div><div>1) Move `<font face="Menlo">|</font>` and `<font face="Menlo">^</font>` into their own parallel precedence groups named <b>BitwiseOr</b> and <b>BitwiseXor</b>, just above RangeFormation.</div><div>2) Move `<font face="Menlo">&amp;</font>` into its own group <b>BitwiseAnd</b>, just above both BitwiseOr and BitwiseXor.</div><div>3) Move <b>BitwiseShift</b> (i.e. `<font face="Menlo">&lt;&lt;</font>` and `<font face="Menlo">&gt;&gt;</font>`) just above BitwiseAnd.</div><div><br></div><div>That would make it so that rarely occurring*) expressions mixing `^` and `|` would now need parenthesising, but either of them would work together with `&amp;`, `&lt;&lt;`, and `&gt;&gt;` just like they do in C (and just the way binary addition relates to multiplication in the conventions of mathematics).</div><div><br></div><div>*) E.g. none found in <a href="https://graphics.stanford.edu/~seander/bithacks.html" target="_blank">https://graphics.stanford.<wbr>edu/~seander/bithacks.html</a>.</div><div><br></div><div>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 `<font face="Menlo">a &amp; b + c</font>`, `<font face="Menlo">a | b + c</font>`, and `<font face="Menlo">a &lt;&lt; b - c</font>` all compile in both C and Swift, but are parsed in exactly opposing ways.</div><div><br></div><div>The whole hierarchy I&#39;m proposing is illustrated in the attachment below, with all changes found in the top part above RangeFormation.</div><div><br></div><div>— Pyry</div><div><br></div></div></blockquote></div></div></div></blockquote></div></div></div>