<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Interesting, I like the idea of changing how precedence is defined, but I’m curious how under the new scheme we would go about inserting a new operator unambiguously? For example:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>#precedence(•, lessThan: *)</div><span class="Apple-tab-span" style="white-space: pre;">        </span>#precedence(~,&nbsp;lessThan: *)<div class=""><br class=""><div class="">Assuming these are defined in separate modules, how do we determine the order of • and ~?</div><div class=""><br class=""></div><div class="">On a related note, I never encounter precedence issues because I always use parenthesis, since I know I’ll just forget the precedence rules so it’d be a mistake for me to rely on them. If we’re adding operators in precedence hierarchies then that only makes it even harder to learn/remember, so I wonder if we might actually be better served by removing precedence entirely? i.e- the compiler would instead require the use of parenthesis to eliminate ambiguity like so:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let a = 5 + 6<span class="Apple-tab-span" style="white-space:pre">                        </span>// Correct, as there aren’t enough operators for ambiguity</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let b = 5 + 6 * 7 + 8<span class="Apple-tab-span" style="white-space:pre">                </span>// Incorrect, as it relies on precedence to be meaningful</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let c = (5 + 6) * (7 + 8)<span class="Apple-tab-span" style="white-space:pre">        </span>// Correct, as parenthesis eliminates ambiguity/the need for precedence</div><div class=""><br class=""></div><div class="">This not only eliminates the need to learn, remember and/or lookup precedence, but it’s clearer and avoids mistakes, and IMO it’s actually more readable despite the added noise.</div><br class=""><div><blockquote type="cite" class=""><div class="">On 3 Apr 2016, at 10:36, Антон Жилин via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">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 class=""><br class=""></div><div class=""><a href="https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md" class="">https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md</a></div><div class=""><br class=""></div><div class=""><div class=""><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'" class="">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" class="">Replace syntax of operator definition:</p><div class="" 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)" class=""><span class="" style="color:rgb(167,29,93)">infix</span> <span class="" style="color:rgb(167,29,93)">operator</span> <span class="" style="color:rgb(167,29,93)">&lt;&gt;</span> { <span class="" style="color:rgb(167,29,93)">precedence</span> <span class="" style="color:rgb(0,134,179)">100</span> <span class="" style="color:rgb(167,29,93)">associativity</span> <span class="" 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" class="">With a directive:</p><div class="" 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)" class="">#<span class="" style="color:rgb(167,29,93)">operator</span>(<span class="" style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span class="" style="color:rgb(167,29,93)">infix</span>, <span class="" style="color:rgb(167,29,93)">associativity</span>: <span class="" 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" class="">Also replace numeric definition of precedence with separate comparative precedence definitions:</p><div class="" 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)" class="">#<span class="" style="color:rgb(167,29,93)">precedence</span>(<span class="" style="color:rgb(167,29,93)">+</span>, lessThan: <span class="" style="color:rgb(167,29,93)">*</span>)
#<span class="" style="color:rgb(167,29,93)">precedence</span>(<span class="" style="color:rgb(167,29,93)">+</span>, equalTo: <span class="" 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" class="">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" class="">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'" class=""><a id="user-content-motivation" class="" 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"></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'" class=""><a id="user-content-problems-with-numeric-definition-of-precedence" class="" 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"></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" class="">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" class="">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)" class="">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)" class="">??</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)" class="">&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)" class="">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" class="">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)" class="">&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)" class="">??</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'" class=""><a id="user-content-problems-with-a-single-precedence-hierarchy" class="" 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"></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" class="">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" class="">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)" class="">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)" class="">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" class="">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)" class="">&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)" class="">/</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'" class=""><a id="user-content-problems-with-current-operator-definition-syntax" class="" 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"></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" class="">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'" class=""><a id="user-content-conflicts-of-operator-definitions" class="" 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"></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" class="">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" class="">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)" class="">A</code>:</p><div class="" 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)" class=""><span class="" style="color:rgb(167,29,93)">infix</span> <span class="" style="color:rgb(167,29,93)">operator</span> <span class="" style="color:rgb(167,29,93)">|&gt;</span> { <span class="" style="color:rgb(167,29,93)">precedence</span> <span class="" style="color:rgb(0,134,179)">137</span> <span class="" style="color:rgb(167,29,93)">associativity</span> <span class="" 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" class="">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)" class="">B</code>:</p><div class="" 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)" class=""><span class="" style="color:rgb(167,29,93)">infix</span> <span class="" style="color:rgb(167,29,93)">operator</span> <span class="" style="color:rgb(167,29,93)">|&gt;</span> { <span class="" style="color:rgb(167,29,93)">precedence</span> <span class="" style="color:rgb(0,134,179)">138</span> <span class="" style="color:rgb(167,29,93)">associativity</span> <span class="" 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'" class=""><a id="user-content-proposed-solution" class="" 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"></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'" class=""><a id="user-content-change-syntax-for-operator-definition" class="" 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"></a>Change syntax for operator definition</h3><div class="" 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)" class="">#<span class="" style="color:rgb(167,29,93)">operator</span>(<span class="" style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span class="" style="color:rgb(167,29,93)">infix</span>, <span class="" style="color:rgb(167,29,93)">associativity</span>: <span class="" style="color:rgb(167,29,93)">left</span>)
#<span class="" style="color:rgb(167,29,93)">operator</span>(<span class="" style="color:rgb(167,29,93)">!</span>, fixity: <span class="" 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" class="">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)" class="">#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)" class="">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)" class="">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)" class="">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)" class="">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)" class="">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)" class="">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)" class="">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)" class="">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'" class=""><a id="user-content-comparative-precedence" class="" 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"></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" class="">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)" class="">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)" class="">#precedence</code>&nbsp;directive:</p><div class="" 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)" class="">#<span class="" style="color:rgb(167,29,93)">precedence</span>(<span class="" style="color:rgb(167,29,93)">+</span>, lessThan: <span class="" style="color:rgb(167,29,93)">*</span>)
#<span class="" style="color:rgb(167,29,93)">precedence</span>(<span class="" style="color:rgb(167,29,93)">*</span>, equalTo: <span class="" 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" class="">Omission of parentheses is allowed only when precedence between the two operators is defined.</p><div class="" 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)" class=""><span class="" style="color:rgb(0,134,179)">1</span> <span class="" style="color:rgb(167,29,93)">+</span> <span class="" style="color:rgb(0,134,179)">2</span> <span class="" style="color:rgb(167,29,93)">*</span> <span class="" style="color:rgb(0,134,179)">3</span>  <span class="" style="color:rgb(150,152,150)">// ok</span>
<span class="" style="color:rgb(0,134,179)">1</span> <span class="" style="color:rgb(167,29,93)">+</span> <span class="" style="color:rgb(0,134,179)">2</span> <span class="" style="color:rgb(167,29,93)">-</span> <span class="" style="color:rgb(0,134,179)">3</span>  <span class="" style="color:rgb(150,152,150)">// error!</span>
#<span class="" style="color:rgb(167,29,93)">precedence</span>(<span class="" style="color:rgb(167,29,93)">-</span>, equalTo: <span class="" style="color:rgb(167,29,93)">+</span>)
<span class="" style="color:rgb(0,134,179)">1</span> <span class="" style="color:rgb(167,29,93)">+</span> <span class="" style="color:rgb(0,134,179)">2</span> <span class="" style="color:rgb(167,29,93)">-</span> <span class="" style="color:rgb(0,134,179)">3</span>  <span class="" 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" class="">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'" class=""><a id="user-content-conflict-resolution" class="" 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"></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" class="">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 class="" 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)" class="">#<span class="" style="color:rgb(167,29,93)">precedence</span>(<span class="" style="color:rgb(167,29,93)">*</span>, lessThan: <span class="" style="color:rgb(167,29,93)">+</span>)  <span class="" 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" class="">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)" class="">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)" class="">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)" class="">associativity: right</code>.</p><div class="" 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)" class="">#<span class="" style="color:rgb(167,29,93)">operator</span>(<span class="" style="color:rgb(167,29,93)">!</span>, fixity: <span class="" style="color:rgb(167,29,93)">prefix</span>)  <span class="" style="color:rgb(150,152,150)">// ok, duplicated definitions</span>
#<span class="" style="color:rgb(167,29,93)">operator</span>(<span class="" style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span class="" style="color:rgb(167,29,93)">infix</span>)
#<span class="" style="color:rgb(167,29,93)">operator</span>(<span class="" style="color:rgb(167,29,93)">&lt;&gt;</span>, fixity: <span class="" style="color:rgb(167,29,93)">infix</span>, <span class="" style="color:rgb(167,29,93)">associativity</span>: <span class="" style="color:rgb(167,29,93)">left</span>)  <span class="" style="color:rgb(150,152,150)">// ok, now left associative</span>
#<span class="" style="color:rgb(167,29,93)">operator</span>(<span class="" style="color:rgb(167,29,93)">+</span>, fixity: <span class="" style="color:rgb(167,29,93)">infix</span>, <span class="" style="color:rgb(167,29,93)">associativity</span>: <span class="" style="color:rgb(167,29,93)">right</span>)  <span class="" 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" class="">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'" class=""><a id="user-content-detailed-design" class="" 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"></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" class=""><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)" class="">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)" class="">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)" class="">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)" class="">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)" class="">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" class="">Directives with following (informal) syntax will be added:</p><div class="" 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)" class="">#<span class="" style="color:rgb(167,29,93)">operator</span>(OPERATOR_NAME, fixity: FIXITY)
#<span class="" style="color:rgb(167,29,93)">operator</span>(OPERATOR_NAME, fixity: <span class="" style="color:rgb(167,29,93)">infix</span>, <span class="" style="color:rgb(167,29,93)">associativity</span>: ASSOCIATIVITY)
#<span class="" style="color:rgb(167,29,93)">precedence</span>(OPERATOR_NAME, lessThan: OPERATOR_NAME)
#<span class="" 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'" class=""><a id="user-content-impact-on-existing-code" class="" 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"></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" class="">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)" class="">#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" class="">More importantly, it needs to be discussed what operator precedence rules do&nbsp;<em class="">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" class="">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'" class=""><a id="user-content-alternatives-considered" class="" 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"></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'" class=""><a id="user-content-leave-current-operator-syntax-but-change-precedence" class="" 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"></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" class=""><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)" class="">#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 class="" 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)" class=""><span class="" style="color:rgb(167,29,93)">prefix</span> <span class="" style="color:rgb(167,29,93)">operator</span> <span class="" style="color:rgb(167,29,93)">!</span> { }
<span class="" style="color:rgb(167,29,93)">infix</span> <span class="" style="color:rgb(167,29,93)">operator</span> <span class="" style="color:rgb(167,29,93)">|&gt;</span> { }
<span class="" style="color:rgb(167,29,93)">infix</span> <span class="" style="color:rgb(167,29,93)">operator</span> <span class="" style="color:rgb(167,29,93)">&lt;&gt;</span> { <span class="" style="color:rgb(167,29,93)">associativity</span> <span class="" 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;" class="">If body of operator can only contain associativity (in some cases), then the existence of body itself makes no sense.</div></div></div></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>