<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div>See inline</div><div><br>Am 03.04.2016 um 13:26 schrieb Ross O'Brien via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt;:<br><br></div><blockquote type="cite"><div><div dir="ltr">There is a problem here of duplicated operators or custom precedence, and how that gets passed between modules.<div>Assume there are three modules, A, B and C. B defines a custom operator **. A and C each define a custom operator ++, and their meanings are different (though, even if their meanings were the same, I'm not sure if they could unify).</div><div><br></div><div>Module D uses A and B as dependencies and sets a custom precedence on ++ and **. Module E uses B and C and has a different precedence on ++ and **. You're working on Module F which uses D and E. Which ++ and which precedence does F get implicitly?</div><div><br></div></div></div></blockquote><div><br></div><div>We could allow operator precedence overriding to resolve ambiguity. However this overriding should only be module internal since it would override the existing precedences in the other modules.</div><div><br></div><div>@AHTOH</div><div>Why do you use #keyword ?</div><div>I think defining a operator with</div><div><br></div><div>&nbsp; &nbsp; infix operator + {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;associativity: left</div><div>&nbsp; &nbsp; }</div><div><br></div><div>is perfectly fine since it is similar to class/struct/enum declaration.</div><div><br></div><div>&nbsp; &nbsp; // and it's precedence</div><div>&nbsp; &nbsp; precedence(+ lessThan *)</div><div><br></div><div>Note the missing "," and ":" before and after "lessThan" in order to give both operators the same importance&nbsp;<span style="background-color: rgba(255, 255, 255, 0);">(minor issue).</span></div><div><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div><span style="background-color: rgba(255, 255, 255, 0);">I feel that</span></div><div><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div><span style="background-color: rgba(255, 255, 255, 0);">&nbsp; &nbsp; #precedence(+, lessThan: *)</span></div><div><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div><span style="background-color: rgba(255, 255, 255, 0);">puts too much importance on the first operator.</span></div><div><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div><span style="background-color: rgba(255, 255, 255, 0);">Best regards</span></div><div><span style="background-color: rgba(255, 255, 255, 0);">- Maximilian</span></div><br><blockquote type="cite"><div><div dir="ltr"><div>I'm wondering whether we can treat operators the way we recently decided to treat selectors: if there is an ambiguity, it should be possible not just to specify which module they came from, but their fixity or argument types. If module D decides that '++' should refer to 'traditional postfix number incrementation', and F decides that it should be an infix 'conjoin two numbers as a string and turn the result into a number (e.g. 5 ++ 4 -&gt; 54)' then a #selector-like operator signature would come in really handy.</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Apr 3, 2016 at 12:10 PM, Taras Zakharko via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">I think this is a great suggestion! One potential problem I can see (if I understood this correctly) is that modules are allowed to set up their own precedence rules for operators defined elsewhere. I think this might lead to some difficult to debug errors if a developer of one module (who is used to certain conventions) then has to work with a different, independent module (where the conventions are different). This is one area where numerical precedence weights seem to be superior as they at least refer to a common subjective coordinate system.&nbsp;<div><br></div><div>Maybe one should also have visibility for precedence, for instance having precedence module-internal by default?<div><br></div><div>Best,&nbsp;</div><div><br></div><div>&nbsp;— Taras &nbsp;<div><div><br><div><blockquote type="cite"><div><div class="h5"><div>On 03 Apr 2016, at 11:36, Антон Жилин via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br></div></div><div><div><div class="h5"><div dir="ltr">Swift 2.2 is out, and I restart discussion on syntax for custom operators. I insist that this time we should focus less on linguistic aspects.<div><br></div><div><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md" target="_blank">https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md</a></div><div><br></div><div><div><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'">Introduction</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Replace syntax of operator definition:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(167,29,93)">infix</span> <span style="color:rgb(167,29,93)">operator</span> <span style="color:rgb(167,29,93)">&lt;&gt;</span> { <span style="color:rgb(167,29,93)">precedence</span> <span style="color:rgb(0,134,179)">100</span> <span style="color:rgb(167,29,93)">associativity</span> <span style="color:rgb(167,29,93)">left</span> }</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">With a directive:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)">#<span style="color:rgb(167,29,93)">operator</span>(<span style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span style="color:rgb(167,29,93)">infix</span>, <span style="color:rgb(167,29,93)">associativity</span>: <span style="color:rgb(167,29,93)">left</span>)</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Also replace numeric definition of precedence with separate comparative precedence definitions:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)">#<span style="color:rgb(167,29,93)">precedence</span>(<span style="color:rgb(167,29,93)">+</span>, lessThan: <span style="color:rgb(167,29,93)">*</span>)
#<span style="color:rgb(167,29,93)">precedence</span>(<span style="color:rgb(167,29,93)">+</span>, equalTo: <span style="color:rgb(167,29,93)">-</span>)</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Swift-evolution thread:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution" style="color:rgb(64,120,192);text-decoration:none;background-color:transparent" target="_blank">link to the discussion thread for that proposal</a></p><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1;background-color:transparent" target="_blank"></a>Motivation</h2><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Problems with numeric definition of precedence</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">In the beginning, operators had nice precedence values: 90, 100, 110, 120, 130, 140, 150, 160.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">As time went, new and new operators were introduced. Precedence could not be simply changed, as this would be a breaking change. Ranges got precedence 135,&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">as</code>&nbsp;got precedence 132.&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">??</code>&nbsp;had precedence greater than&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">&lt;</code>, but less than<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">as</code>, so it had to be given precedence 131.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Now it is not possible to insert any custom operator between&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">&lt;</code>&nbsp;and&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">??</code>. It is an inevitable consequence of current design: it will be impossible to insert an operator between two existing ones at some point.</p><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Problems with a single precedence hierarchy</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Currently, if an operator wants to define precedence by comparison to one operator, it must do so for all other operators.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">In many cases, this is not wished. Example:&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">a &amp; b &lt; c</code>&nbsp;is a common error pattern.&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">a / b as Double</code>&nbsp;is another one. C++ compilers sometimes emit warnings on these. Swift does not.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">The root of the problem is that precedence is defined between all operators. If&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">&amp;</code>&nbsp;had precedence defined only by comparison to other bitwise operators and&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">/</code>&nbsp;– only to arithmetic operators, we would have to place parentheses in such places, not get subtle bugs, and not ever have to look at the huge operator precedence table.</p><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Problems with current operator definition syntax</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Some argue that current operator syntax is not consistent with other language constructs. Properties of operators have dictionary semantics and should be defined as such. It is a rather weak argument right now, but after reworking of precedence, the new syntax will be more to place. More reasons are given below.</p><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Conflicts of operator definitions</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Consider two operator definitions in different modules.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Module&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">A</code>:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(167,29,93)">infix</span> <span style="color:rgb(167,29,93)">operator</span> <span style="color:rgb(167,29,93)">|&gt;</span> { <span style="color:rgb(167,29,93)">precedence</span> <span style="color:rgb(0,134,179)">137</span> <span style="color:rgb(167,29,93)">associativity</span> <span style="color:rgb(167,29,93)">left</span> }</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Module&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">B</code>:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(167,29,93)">infix</span> <span style="color:rgb(167,29,93)">operator</span> <span style="color:rgb(167,29,93)">|&gt;</span> { <span style="color:rgb(167,29,93)">precedence</span> <span style="color:rgb(0,134,179)">138</span> <span style="color:rgb(167,29,93)">associativity</span> <span style="color:rgb(167,29,93)">left</span> }</pre></div><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1;background-color:transparent" target="_blank"></a>Proposed solution</h2><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Change syntax for operator definition</h3><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)">#<span style="color:rgb(167,29,93)">operator</span>(<span style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span style="color:rgb(167,29,93)">infix</span>, <span style="color:rgb(167,29,93)">associativity</span>: <span style="color:rgb(167,29,93)">left</span>)
#<span style="color:rgb(167,29,93)">operator</span>(<span style="color:rgb(167,29,93)">!</span>, fixity: <span style="color:rgb(167,29,93)">postfix</span>)</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">First parameter of&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">#operator</code>&nbsp;directive is name of the operator. Then goes required parameter&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">fixity</code>&nbsp;that can be&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">infix</code>,<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">prefix</code>, or&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">postfix</code>. Then, for&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">infix</code>&nbsp;operators, goes optional&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">associativity</code>&nbsp;parameter that can be&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">left</code>&nbsp;or&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">right</code>.</p><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Comparative precedence</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Remove&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">precedence</code>&nbsp;property from operator definitions. Instead, introduce&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">#precedence</code>&nbsp;directive:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)">#<span style="color:rgb(167,29,93)">precedence</span>(<span style="color:rgb(167,29,93)">+</span>, lessThan: <span style="color:rgb(167,29,93)">*</span>)
#<span style="color:rgb(167,29,93)">precedence</span>(<span style="color:rgb(167,29,93)">*</span>, equalTo: <span style="color:rgb(167,29,93)">/</span>)</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Omission of parentheses is allowed only when precedence between the two operators is defined.</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(0,134,179)">1</span> <span style="color:rgb(167,29,93)">+</span> <span style="color:rgb(0,134,179)">2</span> <span style="color:rgb(167,29,93)">*</span> <span style="color:rgb(0,134,179)">3</span>  <span style="color:rgb(150,152,150)">// ok</span>
<span style="color:rgb(0,134,179)">1</span> <span style="color:rgb(167,29,93)">+</span> <span style="color:rgb(0,134,179)">2</span> <span style="color:rgb(167,29,93)">-</span> <span style="color:rgb(0,134,179)">3</span>  <span style="color:rgb(150,152,150)">// error!</span>
#<span style="color:rgb(167,29,93)">precedence</span>(<span style="color:rgb(167,29,93)">-</span>, equalTo: <span style="color:rgb(167,29,93)">+</span>)
<span style="color:rgb(0,134,179)">1</span> <span style="color:rgb(167,29,93)">+</span> <span style="color:rgb(0,134,179)">2</span> <span style="color:rgb(167,29,93)">-</span> <span style="color:rgb(0,134,179)">3</span>  <span style="color:rgb(150,152,150)">// now ok</span></pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Precedence equality can only be defined for operators with same associativity.</p><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Conflict resolution</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Precedence rules can be added freely across modules. Ability to omit parentheses around more operators will not break any code in included modules. On the other hand, conflicting precedence rules result in an error:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)">#<span style="color:rgb(167,29,93)">precedence</span>(<span style="color:rgb(167,29,93)">*</span>, lessThan: <span style="color:rgb(167,29,93)">+</span>)  <span style="color:rgb(150,152,150)">// error, previously defined `+` &lt; `*`</span></pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Operator definitions do nut cause conflicts, unless they are&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">infix</code>&nbsp;and one of them has&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">associativity: left</code>, but another one has&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">associativity: right</code>.</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)">#<span style="color:rgb(167,29,93)">operator</span>(<span style="color:rgb(167,29,93)">!</span>, fixity: <span style="color:rgb(167,29,93)">prefix</span>)  <span style="color:rgb(150,152,150)">// ok, duplicated definitions</span>
#<span style="color:rgb(167,29,93)">operator</span>(<span style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span style="color:rgb(167,29,93)">infix</span>)
#<span style="color:rgb(167,29,93)">operator</span>(<span style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span style="color:rgb(167,29,93)">infix</span>, <span style="color:rgb(167,29,93)">associativity</span>: <span style="color:rgb(167,29,93)">left</span>)  <span style="color:rgb(150,152,150)">// ok, now left associative</span>
#<span style="color:rgb(167,29,93)">operator</span>(<span style="color:rgb(167,29,93)">+</span>, fixity: <span style="color:rgb(167,29,93)">infix</span>, <span style="color:rgb(167,29,93)">associativity</span>: <span style="color:rgb(167,29,93)">right</span>)  <span style="color:rgb(150,152,150)">// error: associativity conflict</span></pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">So, if two modules define a custom operator with somewhat similar semantics (at least associativity), they can be used together. Prefix and postfix operators can never have conflicts in definitions. If they define different precedence by comparison to same operators, then, most probably, they had completely different semantics, and the situation is similar to conflict of functions.</p><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1;background-color:transparent" target="_blank"></a>Detailed design</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">operator</code>&nbsp;keyword and local keywords&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">associativity</code>,&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">precedence</code>,&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">left</code>,&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">right</code>&nbsp;will be removed.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Directives with following (informal) syntax will be added:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)">#<span style="color:rgb(167,29,93)">operator</span>(OPERATOR_NAME, fixity: FIXITY)
#<span style="color:rgb(167,29,93)">operator</span>(OPERATOR_NAME, fixity: <span style="color:rgb(167,29,93)">infix</span>, <span style="color:rgb(167,29,93)">associativity</span>: ASSOCIATIVITY)
#<span style="color:rgb(167,29,93)">precedence</span>(OPERATOR_NAME, lessThan: OPERATOR_NAME)
#<span style="color:rgb(167,29,93)">precedence</span>(OPERATOR_NAME, equalTo: OPERATOR_NAME)</pre></div><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1;background-color:transparent" target="_blank"></a>Impact on existing code</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">Standard library operator declarations will need to be rewritten. Some of the existing precedence rules will need to be rewritten using&nbsp;<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">#precedence</code>&nbsp;directive.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">More importantly, it needs to be discussed what operator precedence rules do&nbsp;<em>not</em>&nbsp;need to be retained.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px">User defined operators will need to be rewritten as well. But precedence will have to be defined by the user. Meanwhile, we can automatically insert parentheses to user code where needed.</p><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1;background-color:transparent" target="_blank"></a>Alternatives considered</h2><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'"><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence" style="color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2;background-color:transparent" target="_blank"></a>Leave current operator syntax (but change precedence)</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">#precedence</code>&nbsp;does not make sense to be defined inside of operator definition, as it describes relationship of two operators. If so, then we are left with the following declaration syntax:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(167,29,93)">prefix</span> <span style="color:rgb(167,29,93)">operator</span> <span style="color:rgb(167,29,93)">!</span> { }
<span style="color:rgb(167,29,93)">infix</span> <span style="color:rgb(167,29,93)">operator</span> <span style="color:rgb(167,29,93)">|&gt;</span> { }
<span style="color:rgb(167,29,93)">infix</span> <span style="color:rgb(167,29,93)">operator</span> <span style="color:rgb(167,29,93)">&lt;&gt;</span> { <span style="color:rgb(167,29,93)">associativity</span> <span style="color:rgb(167,29,93)">left</span> }</pre></div><div style="margin-top:0px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px;margin-bottom:0px!important">If body of operator can only contain associativity (in some cases), then the existence of body itself makes no sense.</div></div></div></div></div></div><span class="">
_______________________________________________<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/mailman/listinfo/swift-evolution</a><br></span></div></blockquote></div><br></div></div></div></div></div><br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>