# \[Proposal\] Custom operators

**URL:** <https://forums.swift.org/t/proposal-custom-operators/2046>\
**Category:** Discussion\
**Created:** [April 3, 2016, 9:36am UTC](https://forums.swift.org/t/proposal-custom-operators/2046 "2016-04-03T09:36:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [April 3, 2016, 9:36am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/1 "2016-04-03T09:36:00Z")

</div>

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.

[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)

Introduction

Replace syntax of operator definition:

infix operator \<\> { precedence 100 associativity left }

With a directive:

#operator(\<\>, fixity: infix, associativity: left)

Also replace numeric definition of precedence with separate comparative  
precedence definitions:

#precedence(+, lessThan: \*)  
#precedence(+, equalTo: -)

Swift-evolution thread: link to the discussion thread for that proposal  
\<[https://lists.swift.org/pipermail/swift-evolution&gt](https://lists.swift.org/pipermail/swift-evolution&gt);  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt);  
Motivation  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems)  
with numeric definition of precedence

In the beginning, operators had nice precedence values: 90, 100, 110, 120,  
130, 140, 150, 160.

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, as got precedence 132. ?? had precedence greater than \<,  
but less thanas, so it had to be given precedence 131.

Now it is not possible to insert any custom operator between \< and ??. It  
is an inevitable consequence of current design: it will be impossible to  
insert an operator between two existing ones at some point.  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems)  
with a single precedence hierarchy

Currently, if an operator wants to define precedence by comparison to one  
operator, it must do so for all other operators.

In many cases, this is not wished. Example: a & b \< c is a common error  
pattern. a / b as Double is another one. C++ compilers sometimes emit  
warnings on these. Swift does not.

The root of the problem is that precedence is defined between all  
operators. If & had precedence defined only by comparison to other bitwise  
operators and / – 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.  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems)  
with current operator definition syntax

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.  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts)  
of operator definitions

Consider two operator definitions in different modules.

Module A:

infix operator |\> { precedence 137 associativity left }

Module B:

infix operator |\> { precedence 138 associativity left }

\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed)  
solution  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change)  
syntax for operator definition

#operator(\<\>, fixity: infix, associativity: left)  
#operator(!, fixity: postfix)

First parameter of #operator directive is name of the operator. Then goes  
required parameter fixity that can be infix,prefix, or postfix. Then, for  
infix operators, goes optional associativity parameter that can be left or  
right.  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative)  
precedence

Remove precedence property from operator definitions. Instead, introduce  
#precedence directive:

#precedence(+, lessThan: \*)  
#precedence(\*, equalTo: /)

Omission of parentheses is allowed only when precedence between the two  
operators is defined.

1 + 2 \* 3 // ok1 + 2 - 3 // error!  
#precedence(-, equalTo: +)1 + 2 - 3 // now ok

Precedence equality can only be defined for operators with same  
associativity.  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict)  
resolution

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:

#precedence(\*, lessThan: +) // error, previously defined `+` \< `*`

Operator definitions do nut cause conflicts, unless they are infix and one  
of them has associativity: left, but another one has associativity: right.

#operator(!, fixity: prefix) // ok, duplicated definitions  
#operator(\<\>, fixity: infix)  
#operator(\<\>, fixity: infix, associativity: left) // ok, now left associative  
#operator(+, fixity: infix, associativity: right) // error:  
associativity conflict

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.  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed)  
design

operator keyword and local keywords associativity, precedence, left, right will  
be removed.

Directives with following (informal) syntax will be added:

#operator(OPERATOR\_NAME, fixity: FIXITY)  
#operator(OPERATOR\_NAME, fixity: infix, associativity: ASSOCIATIVITY)  
#precedence(OPERATOR\_NAME, lessThan: OPERATOR\_NAME)  
#precedence(OPERATOR\_NAME, equalTo: OPERATOR\_NAME)

\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact)  
on existing code

Standard library operator declarations will need to be rewritten. Some of  
the existing precedence rules will need to be rewritten using #precedence  
directive.

More importantly, it needs to be discussed what operator precedence rules  
do \*not\* need to be retained.

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.  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives)  
considered  
\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave)  
current operator syntax (but change precedence)

#precedence 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:

prefix operator ! { }infix operator |\> { }infix operator \<\> {  
associativity left }

If body of operator can only contain associativity (in some cases), then  
the existence of body itself makes no sense.

---

<div class="post-metadata">

**Author:** ![Haravikk3](https://avatars.discourse-cdn.com/v4/letter/h/df705f/32.png) [@Haravikk3](https://forums.swift.org/u/Haravikk3)\
**Post date:** [April 3, 2016, 10:31am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/2 "2016-04-03T10:31:28Z")

</div>

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:

&nbsp;&nbsp;#precedence(•, lessThan: \*)  
&nbsp;&nbsp;#precedence(~, lessThan: \*)

Assuming these are defined in separate modules, how do we determine the order of • and ~?

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:

&nbsp;&nbsp;let a = 5 + 6 // Correct, as there aren’t enough operators for ambiguity  
&nbsp;&nbsp;let b = 5 + 6 \* 7 + 8 // Incorrect, as it relies on precedence to be meaningful  
&nbsp;&nbsp;let c = (5 + 6) \* (7 + 8) // Correct, as parenthesis eliminates ambiguity/the need for precedence

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.

> **···**
>
> > On 3 Apr 2016, at 10:36, Антон Жилин via swift-evolution \<swift-evolution@swift.org\> wrote:
> > 
> > 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.
> > 
> > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > 
> > Introduction
> > 
> > Replace syntax of operator definition:
> > 
> > infix operator \<\> { precedence 100 associativity left }  
> > With a directive:
> > 
> > #operator(\<\>, fixity: infix, associativity: left)  
> > Also replace numeric definition of precedence with separate comparative precedence definitions:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(+, equalTo: -)  
> > Swift-evolution thread: link to the discussion thread for that proposal \<[https://lists.swift.org/pipermail/swift-evolution&gt](https://lists.swift.org/pipermail/swift-evolution&gt);  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt;Motivation](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt;Motivation)
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems) with numeric definition of precedence
> > 
> > In the beginning, operators had nice precedence values: 90, 100, 110, 120, 130, 140, 150, 160.
> > 
> > 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, as got precedence 132. ?? had precedence greater than \<, but less thanas, so it had to be given precedence 131.
> > 
> > Now it is not possible to insert any custom operator between \< and ??. It is an inevitable consequence of current design: it will be impossible to insert an operator between two existing ones at some point.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems) with a single precedence hierarchy
> > 
> > Currently, if an operator wants to define precedence by comparison to one operator, it must do so for all other operators.
> > 
> > In many cases, this is not wished. Example: a & b \< c is a common error pattern. a / b as Double is another one. C++ compilers sometimes emit warnings on these. Swift does not.
> > 
> > The root of the problem is that precedence is defined between all operators. If & had precedence defined only by comparison to other bitwise operators and / – 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems) with current operator definition syntax
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts) of operator definitions
> > 
> > Consider two operator definitions in different modules.
> > 
> > Module A:
> > 
> > infix operator |\> { precedence 137 associativity left }  
> > Module B:
> > 
> > infix operator |\> { precedence 138 associativity left }  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed) solution
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change) syntax for operator definition
> > 
> > #operator(\<\>, fixity: infix, associativity: left)  
> > #operator(!, fixity: postfix)  
> > First parameter of #operator directive is name of the operator. Then goes required parameter fixity that can be infix,prefix, or postfix. Then, for infix operators, goes optional associativity parameter that can be left or right.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative) precedence
> > 
> > Remove precedence property from operator definitions. Instead, introduce #precedence directive:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(\*, equalTo: /)  
> > Omission of parentheses is allowed only when precedence between the two operators is defined.
> > 
> > 1 + 2 \* 3 // ok  
> > 1 + 2 - 3 // error!  
> > #precedence(-, equalTo: +)  
> > 1 + 2 - 3 // now ok  
> > Precedence equality can only be defined for operators with same associativity.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict) resolution
> > 
> > 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:
> > 
> > #precedence(\*, lessThan: +) // error, previously defined `+` \< `*`  
> > Operator definitions do nut cause conflicts, unless they are infix and one of them has associativity: left, but another one has associativity: right.
> > 
> > #operator(!, fixity: prefix) // ok, duplicated definitions  
> > #operator(\<\>, fixity: infix)  
> > #operator(\<\>, fixity: infix, associativity: left) // ok, now left associative  
> > #operator(+, fixity: infix, associativity: right) // error: associativity conflict  
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed) design
> > 
> > operator keyword and local keywords associativity, precedence, left, right will be removed.
> > 
> > Directives with following (informal) syntax will be added:
> > 
> > #operator(OPERATOR\_NAME, fixity: FIXITY)  
> > #operator(OPERATOR\_NAME, fixity: infix, associativity: ASSOCIATIVITY)  
> > #precedence(OPERATOR\_NAME, lessThan: OPERATOR\_NAME)  
> > #precedence(OPERATOR\_NAME, equalTo: OPERATOR\_NAME)  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact) on existing code
> > 
> > Standard library operator declarations will need to be rewritten. Some of the existing precedence rules will need to be rewritten using #precedence directive.
> > 
> > More importantly, it needs to be discussed what operator precedence rules do not need to be retained.
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives) considered
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave) current operator syntax (but change precedence)
> > 
> > #precedence 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:
> > 
> > prefix operator ! { }  
> > infix operator |\> { }  
> > infix operator \<\> { associativity left }  
> > If body of operator can only contain associativity (in some cases), then the existence of body itself makes no sense.  
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Taras\_Zakharko1](https://avatars.discourse-cdn.com/v4/letter/t/ecd19e/32.png) [@Taras\_Zakharko1](https://forums.swift.org/u/Taras_Zakharko1)\
**Post date:** [April 3, 2016, 11:10am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/3 "2016-04-03T11:10:20Z")

</div>

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.

Maybe one should also have visibility for precedence, for instance having precedence module-internal by default?

Best,

— Taras

> **···**
>
> > On 03 Apr 2016, at 11:36, Антон Жилин via swift-evolution \<swift-evolution@swift.org\> wrote:
> > 
> > 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.
> > 
> > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > 
> > Introduction
> > 
> > Replace syntax of operator definition:
> > 
> > infix operator \<\> { precedence 100 associativity left }  
> > With a directive:
> > 
> > #operator(\<\>, fixity: infix, associativity: left)  
> > Also replace numeric definition of precedence with separate comparative precedence definitions:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(+, equalTo: -)  
> > Swift-evolution thread: link to the discussion thread for that proposal \<[https://lists.swift.org/pipermail/swift-evolution&gt](https://lists.swift.org/pipermail/swift-evolution&gt);  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt;Motivation](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt;Motivation)
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems) with numeric definition of precedence
> > 
> > In the beginning, operators had nice precedence values: 90, 100, 110, 120, 130, 140, 150, 160.
> > 
> > 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, as got precedence 132. ?? had precedence greater than \<, but less thanas, so it had to be given precedence 131.
> > 
> > Now it is not possible to insert any custom operator between \< and ??. It is an inevitable consequence of current design: it will be impossible to insert an operator between two existing ones at some point.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems) with a single precedence hierarchy
> > 
> > Currently, if an operator wants to define precedence by comparison to one operator, it must do so for all other operators.
> > 
> > In many cases, this is not wished. Example: a & b \< c is a common error pattern. a / b as Double is another one. C++ compilers sometimes emit warnings on these. Swift does not.
> > 
> > The root of the problem is that precedence is defined between all operators. If & had precedence defined only by comparison to other bitwise operators and / – 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems) with current operator definition syntax
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts) of operator definitions
> > 
> > Consider two operator definitions in different modules.
> > 
> > Module A:
> > 
> > infix operator |\> { precedence 137 associativity left }  
> > Module B:
> > 
> > infix operator |\> { precedence 138 associativity left }  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed) solution
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change) syntax for operator definition
> > 
> > #operator(\<\>, fixity: infix, associativity: left)  
> > #operator(!, fixity: postfix)  
> > First parameter of #operator directive is name of the operator. Then goes required parameter fixity that can be infix,prefix, or postfix. Then, for infix operators, goes optional associativity parameter that can be left or right.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative) precedence
> > 
> > Remove precedence property from operator definitions. Instead, introduce #precedence directive:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(\*, equalTo: /)  
> > Omission of parentheses is allowed only when precedence between the two operators is defined.
> > 
> > 1 + 2 \* 3 // ok  
> > 1 + 2 - 3 // error!  
> > #precedence(-, equalTo: +)  
> > 1 + 2 - 3 // now ok  
> > Precedence equality can only be defined for operators with same associativity.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict) resolution
> > 
> > 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:
> > 
> > #precedence(\*, lessThan: +) // error, previously defined `+` \< `*`  
> > Operator definitions do nut cause conflicts, unless they are infix and one of them has associativity: left, but another one has associativity: right.
> > 
> > #operator(!, fixity: prefix) // ok, duplicated definitions  
> > #operator(\<\>, fixity: infix)  
> > #operator(\<\>, fixity: infix, associativity: left) // ok, now left associative  
> > #operator(+, fixity: infix, associativity: right) // error: associativity conflict  
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed) design
> > 
> > operator keyword and local keywords associativity, precedence, left, right will be removed.
> > 
> > Directives with following (informal) syntax will be added:
> > 
> > #operator(OPERATOR\_NAME, fixity: FIXITY)  
> > #operator(OPERATOR\_NAME, fixity: infix, associativity: ASSOCIATIVITY)  
> > #precedence(OPERATOR\_NAME, lessThan: OPERATOR\_NAME)  
> > #precedence(OPERATOR\_NAME, equalTo: OPERATOR\_NAME)  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact) on existing code
> > 
> > Standard library operator declarations will need to be rewritten. Some of the existing precedence rules will need to be rewritten using #precedence directive.
> > 
> > More importantly, it needs to be discussed what operator precedence rules do not need to be retained.
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives) considered
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave) current operator syntax (but change precedence)
> > 
> > #precedence 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:
> > 
> > prefix operator ! { }  
> > infix operator |\> { }  
> > infix operator \<\> { associativity left }  
> > If body of operator can only contain associativity (in some cases), then the existence of body itself makes no sense.  
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [April 3, 2016, 10:45am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/4 "2016-04-03T10:45:48Z")

</div>

> Assuming these are defined in separate modules, how do we determine the

order of • and ~?

By default, priority between any two operators is undefined. If two modules  
don't know about each other, but the user wishes to prioritize them, then  
he will write:

#precedence(•, lessThan: ~)

If • suddenly wishes to cooperate with ~, then it will add directives:

#operator(~, fixity: infix, associativity: left)  
#precedence(•, lessThan: ~)

It doesn't matter if ~ or user have already added them: if they do not  
contain contradictory information, there will be no conflict.

> 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?

That's exactly what I'm trying to do! I propose that there should be no  
hierarchy. Each pair of operators will have to define priority explicitly,  
if they need it.

I'll give an example of what I mean by "removing hierarchy":

#precedence(+, lessThan: \*)  
#precedence(\*, lessThan: ^)  
2 ^ 3 + 6 # error  
#precedence(+, lessThan: ^)  
2 ^ 3 + 6 # now ok

- Anton

> **···**
>
> 2016-04-03 13:31 GMT+03:00 Haravikk \<swift-evolution@haravikk.me\>:
> 
> > 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:
> > 
> > #precedence(•, lessThan: \*)  
> > #precedence(~, lessThan: \*)
> > 
> > Assuming these are defined in separate modules, how do we determine the  
> > order of • and ~?
> > 
> > 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:
> > 
> > let a = 5 + 6 // Correct, as there aren’t enough operators for ambiguity  
> > let b = 5 + 6 \* 7 + 8 // Incorrect, as it relies on precedence to be  
> > meaningful  
> > let c = (5 + 6) \* (7 + 8) // Correct, as parenthesis eliminates  
> > ambiguity/the need for precedence
> > 
> > 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.
> > 
> > On 3 Apr 2016, at 10:36, Антон Жилин via swift-evolution \< \> swift-evolution@swift.org\> wrote:
> > 
> > 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.
> > 
> > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > 
> > Introduction
> > 
> > Replace syntax of operator definition:
> > 
> > infix operator \<\> { precedence 100 associativity left }
> > 
> > With a directive:
> > 
> > #operator(\<\>, fixity: infix, associativity: left)
> > 
> > Also replace numeric definition of precedence with separate comparative  
> > precedence definitions:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(+, equalTo: -)
> > 
> > Swift-evolution thread: link to the discussion thread for that proposal  
> > \<[https://lists.swift.org/pipermail/swift-evolution&gt](https://lists.swift.org/pipermail/swift-evolution&gt);
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt);  
> > Motivation  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems)  
> > with numeric definition of precedence
> > 
> > In the beginning, operators had nice precedence values: 90, 100, 110, 120,  
> > 130, 140, 150, 160.
> > 
> > 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, as got precedence 132. ?? had precedence greater than \<,  
> > but less thanas, so it had to be given precedence 131.
> > 
> > Now it is not possible to insert any custom operator between \< and ??. It  
> > is an inevitable consequence of current design: it will be impossible to  
> > insert an operator between two existing ones at some point.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems)  
> > with a single precedence hierarchy
> > 
> > Currently, if an operator wants to define precedence by comparison to one  
> > operator, it must do so for all other operators.
> > 
> > In many cases, this is not wished. Example: a & b \< c is a common error  
> > pattern. a / b as Double is another one. C++ compilers sometimes emit  
> > warnings on these. Swift does not.
> > 
> > The root of the problem is that precedence is defined between all  
> > operators. If & had precedence defined only by comparison to other  
> > bitwise operators and / – 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems)  
> > with current operator definition syntax
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts)  
> > of operator definitions
> > 
> > Consider two operator definitions in different modules.
> > 
> > Module A:
> > 
> > infix operator |\> { precedence 137 associativity left }
> > 
> > Module B:
> > 
> > infix operator |\> { precedence 138 associativity left }
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed)  
> > solution  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change)  
> > syntax for operator definition
> > 
> > #operator(\<\>, fixity: infix, associativity: left)  
> > #operator(!, fixity: postfix)
> > 
> > First parameter of #operator directive is name of the operator. Then goes  
> > required parameter fixity that can be infix,prefix, or postfix. Then, for  
> > infix operators, goes optional associativity parameter that can be left  
> > or right.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative)  
> > precedence
> > 
> > Remove precedence property from operator definitions. Instead, introduce  
> > #precedence directive:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(\*, equalTo: /)
> > 
> > Omission of parentheses is allowed only when precedence between the two  
> > operators is defined.
> > 
> > 1 + 2 \* 3 // ok1 + 2 - 3 // error!  
> > #precedence(-, equalTo: +)1 + 2 - 3 // now ok
> > 
> > Precedence equality can only be defined for operators with same  
> > associativity.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict)  
> > resolution
> > 
> > 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:
> > 
> > #precedence(\*, lessThan: +) // error, previously defined `+` \< `*`
> > 
> > Operator definitions do nut cause conflicts, unless they are infix and  
> > one of them has associativity: left, but another one has associativity:  
> > right.
> > 
> > #operator(!, fixity: prefix) // ok, duplicated definitions  
> > #operator(\<\>, fixity: infix)  
> > #operator(\<\>, fixity: infix, associativity: left) // ok, now left associative  
> > #operator(+, fixity: infix, associativity: right) // error: associativity conflict
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed)  
> > design
> > 
> > operator keyword and local keywords associativity, precedence, left, right will  
> > be removed.
> > 
> > Directives with following (informal) syntax will be added:
> > 
> > #operator(OPERATOR\_NAME, fixity: FIXITY)  
> > #operator(OPERATOR\_NAME, fixity: infix, associativity: ASSOCIATIVITY)  
> > #precedence(OPERATOR\_NAME, lessThan: OPERATOR\_NAME)  
> > #precedence(OPERATOR\_NAME, equalTo: OPERATOR\_NAME)
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact)  
> > on existing code
> > 
> > Standard library operator declarations will need to be rewritten. Some of  
> > the existing precedence rules will need to be rewritten using #precedence  
> > directive.
> > 
> > More importantly, it needs to be discussed what operator precedence rules  
> > do \*not\* need to be retained.
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives)  
> > considered  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave)  
> > current operator syntax (but change precedence)
> > 
> > #precedence 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:
> > 
> > prefix operator ! { }infix operator |\> { }infix operator \<\> { associativity left }
> > 
> > If body of operator can only contain associativity (in some cases), then  
> > the existence of body itself makes no sense.  
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [April 3, 2016, 6:41pm UTC](https://forums.swift.org/t/proposal-custom-operators/2046/5 "2016-04-03T18:41:00Z")

</div>

\<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/)  
NNNN-operator-precedence.md\>

Another way to eliminate numerical precedence is by using keywords:

infix operator \<\< {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity none  
&nbsp;&nbsp;&nbsp;&nbsp;exponentiative  
}

infix operator \* {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity left  
&nbsp;&nbsp;&nbsp;&nbsp;multiplicative  
}

infix operator + {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity left  
&nbsp;&nbsp;&nbsp;&nbsp;additive  
}

infix operator == {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity none  
&nbsp;&nbsp;&nbsp;&nbsp;comparative  
}

infix operator += {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity right  
&nbsp;&nbsp;&nbsp;&nbsp;assignment  
}

All operators would need to use one of the existing precedence groups (Table 2):

\<[https://developer.apple.com/library/ios/documentation/Swift/Reference/](https://developer.apple.com/library/ios/documentation/Swift/Reference/)  
Swift\_StandardLibrary\_Operators/\>

-- Ben

---

<div class="post-metadata">

**Author:** ![dwaite](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dwaite/32/1200_2.png) [@dwaite](https://forums.swift.org/u/dwaite)\
**Post date:** [April 4, 2016, 5:55am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/6 "2016-04-04T05:55:40Z")

</div>

Interesting model!

If I understand correctly: this changes the precedence from being based on a numeric value, to being represented as a bit of a DAG of precedence groups. A precedence group is defined implicitly for each operator, with one group around each set of operators where equalTo has been declared.

The groups are lazily evaluated, so if an expression can be resolved without ambiguity due to lack of reachability between two individual operators in the DAG, there is no issue/error.

Comments:  
- I wonder if there are cases in the standard operators which would be better modeled as a non-linear chain. The compiler could warn around usage which is defined by operator precedence, but is commonly considered ambiguous or error prone.

For example, if users commonly get confused about the conjunctive and disjunctive levels (logical ‘and’ and ‘or’) being different levels with precedence, you could just omit the lessThan relationship between the two of them. The compiler would then error on ambiguous cases, prompting the user to use parenthesis.

- I’d prefer instead of operator precedence groups just being implicit by use of #precedence equalTo, that the operators are bound to a group explicitly. Something like  
#precedence(+, group: “additive”)  
#precedence(“additive”, lessThan: “multiplicative”)

However, this may create more issues than it solves (two frameworks creating their own custom operators, putting them in custom precedence groups, and the consumer decides the two precedence groups are really equivalent)

-DW

> **···**
>
> > On Apr 3, 2016, at 3:36 AM, Антон Жилин via swift-evolution \<swift-evolution@swift.org\> wrote:
> > 
> > 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.
> > 
> > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)

---

<div class="post-metadata">

**Author:** ![dduan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dduan/32/290_2.png) [@dduan](https://forums.swift.org/u/dduan)\
**Post date:** [April 4, 2016, 6:21pm UTC](https://forums.swift.org/t/proposal-custom-operators/2046/7 "2016-04-04T18:21:47Z")

</div>

> Антон Жилин via swift-evolution \<swift-evolution@...\> writes:

> 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.

I have a few thoughts and a question regarding precedence:

1. I strongly agree that the numeric precedence system is not great. From  
&nbsp;&nbsp;&nbsp;&nbsp;a implementation point of view, the way to specify them in your proposal  
&nbsp;&nbsp;&nbsp;&nbsp;essentially gave all visible operators a partial order, in which we can  
&nbsp;&nbsp;&nbsp;&nbsp;draw a directed gragh with operators being the nodes and their relation  
&nbsp;&nbsp;&nbsp;&nbsp;being arcs. A part of the graph might look like: '^' --\> '\*' --\> '+', the  
&nbsp;&nbsp;&nbsp;&nbsp;nodes being the math operators. We can tell '\*' has a higher precedence  
&nbsp;&nbsp;&nbsp;&nbsp;than '+', '^' has a higher precedence than '\*' and '+', by follwing the  
&nbsp;&nbsp;&nbsp;&nbsp;arcs. If one operator is not reachable from another, and vice versa, then  
&nbsp;&nbsp;&nbsp;&nbsp;composing these two is illegal. We need to teach the compiler this concept.

2. Currently, it's not possible to specify precedence for pre- and postfix  
&nbsp;&nbsp;&nbsp;&nbsp;operators. Chris Lattner has mentioned that the  
&nbsp;&nbsp;&nbsp;&nbsp;following result is not desirable:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;∆x + y

&nbsp;&nbsp;&nbsp;&nbsp;… where ∆ has a lower precendence than + while it's required to have no  
&nbsp;&nbsp;&nbsp;&nbsp;space between ∆ and the operand. My understanding is that if spaces were  
&nbsp;&nbsp;&nbsp;&nbsp;to be allowed here, parsing such expression without ambiguity is a  
&nbsp;&nbsp;&nbsp;&nbsp;non-trivial challenge. So, will it be possible to specify precedence for  
&nbsp;&nbsp;&nbsp;&nbsp;pre/postfix operators under your proposal?

3. It may be a good exercise to work out how would each of the builtin  
&nbsp;&nbsp;&nbsp;&nbsp;operators would be defined with this change and mention it (not the entire  
&nbsp;&nbsp;&nbsp;&nbsp;definition, but the fact that it's possible, or reasons why it produces  
&nbsp;&nbsp;&nbsp;&nbsp;any difference) in the proposal.

- Daniel

---

<div class="post-metadata">

**Author:** ![Felix\_Cloutier1](https://avatars.discourse-cdn.com/v4/letter/f/e47c2d/32.png) [@Felix\_Cloutier1](https://forums.swift.org/u/Felix_Cloutier1)\
**Post date:** [April 3, 2016, 6:49pm UTC](https://forums.swift.org/t/proposal-custom-operators/2046/8 "2016-04-03T18:49:44Z")

</div>

That doesn't sound future-proof. If it was in place and Range hadn't existed since the earliest Swift public release, it wouldn't be possible to define its precedence now.

Félix

> **···**
>
> > Le 3 avr. 2016 à 11:41:00, Ben Rimmington via swift-evolution \<swift-evolution@swift.org\> a écrit :
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/)  
> > NNNN-operator-precedence.md\>
> > 
> > Another way to eliminate numerical precedence is by using keywords:
> > 
> > infix operator \<\< {  
> > &nbsp;&nbsp;&nbsp;associativity none  
> > &nbsp;&nbsp;&nbsp;exponentiative  
> > }
> > 
> > infix operator \* {  
> > &nbsp;&nbsp;&nbsp;associativity left  
> > &nbsp;&nbsp;&nbsp;multiplicative  
> > }
> > 
> > infix operator + {  
> > &nbsp;&nbsp;&nbsp;associativity left  
> > &nbsp;&nbsp;&nbsp;additive  
> > }
> > 
> > infix operator == {  
> > &nbsp;&nbsp;&nbsp;associativity none  
> > &nbsp;&nbsp;&nbsp;comparative  
> > }
> > 
> > infix operator += {  
> > &nbsp;&nbsp;&nbsp;associativity right  
> > &nbsp;&nbsp;&nbsp;assignment  
> > }
> > 
> > All operators would need to use one of the existing precedence groups (Table 2):
> > 
> > \<[https://developer.apple.com/library/ios/documentation/Swift/Reference/](https://developer.apple.com/library/ios/documentation/Swift/Reference/)  
> > Swift\_StandardLibrary\_Operators/\>
> > 
> > -- Ben
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Haravikk3](https://avatars.discourse-cdn.com/v4/letter/h/df705f/32.png) [@Haravikk3](https://forums.swift.org/u/Haravikk3)\
**Post date:** [April 3, 2016, 10:58am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/9 "2016-04-03T10:58:43Z")

</div>

Ah, I misunderstood then, so a warning/error will be raised if no precedence exists? Thanks for the explanation! I’ll probably still favour overkill brackets, but this makes sense.

In any event I’m on +1 for the more standardised syntax and the switch to using #directives, makes a lot of sense since these are really just customisable compiler symbols.

> **···**
>
> > On 3 Apr 2016, at 11:45, Антон Жилин \<antonyzhilin@gmail.com\> wrote:
> > 
> > \> Assuming these are defined in separate modules, how do we determine the order of • and ~?
> > 
> > By default, priority between any two operators is undefined. If two modules don't know about each other, but the user wishes to prioritize them, then he will write:
> > 
> > #precedence(•, lessThan: ~)
> > 
> > If • suddenly wishes to cooperate with ~, then it will add directives:
> > 
> > #operator(~, fixity: infix, associativity: left)  
> > #precedence(•, lessThan: ~)
> > 
> > It doesn't matter if ~ or user have already added them: if they do not contain contradictory information, there will be no conflict.

---

<div class="post-metadata">

**Author:** ![Ross\_O\_Brien](https://avatars.discourse-cdn.com/v4/letter/r/e56c9b/32.png) [@Ross\_O\_Brien](https://forums.swift.org/u/Ross_O_Brien)\
**Post date:** [April 3, 2016, 11:26am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/10 "2016-04-03T11:26:10Z")

</div>

There is a problem here of duplicated operators or custom precedence, and  
how that gets passed between modules.  
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).

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?

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 -\> 54)'  
then a #selector-like operator signature would come in really handy.

> **···**
>
> On Sun, Apr 3, 2016 at 12:10 PM, Taras Zakharko via swift-evolution \< swift-evolution@swift.org\> wrote:
> 
> > 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.
> > 
> > Maybe one should also have visibility for precedence, for instance having  
> > precedence module-internal by default?
> > 
> > Best,
> > 
> > — Taras
> > 
> > On 03 Apr 2016, at 11:36, Антон Жилин via swift-evolution \< \> swift-evolution@swift.org\> wrote:
> > 
> > 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.
> > 
> > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > 
> > Introduction
> > 
> > Replace syntax of operator definition:
> > 
> > infix operator \<\> { precedence 100 associativity left }
> > 
> > With a directive:
> > 
> > #operator(\<\>, fixity: infix, associativity: left)
> > 
> > Also replace numeric definition of precedence with separate comparative  
> > precedence definitions:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(+, equalTo: -)
> > 
> > Swift-evolution thread: link to the discussion thread for that proposal  
> > \<[https://lists.swift.org/pipermail/swift-evolution&gt](https://lists.swift.org/pipermail/swift-evolution&gt);
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt);  
> > Motivation  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems)  
> > with numeric definition of precedence
> > 
> > In the beginning, operators had nice precedence values: 90, 100, 110, 120,  
> > 130, 140, 150, 160.
> > 
> > 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, as got precedence 132. ?? had precedence greater than \<,  
> > but less thanas, so it had to be given precedence 131.
> > 
> > Now it is not possible to insert any custom operator between \< and ??. It  
> > is an inevitable consequence of current design: it will be impossible to  
> > insert an operator between two existing ones at some point.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems)  
> > with a single precedence hierarchy
> > 
> > Currently, if an operator wants to define precedence by comparison to one  
> > operator, it must do so for all other operators.
> > 
> > In many cases, this is not wished. Example: a & b \< c is a common error  
> > pattern. a / b as Double is another one. C++ compilers sometimes emit  
> > warnings on these. Swift does not.
> > 
> > The root of the problem is that precedence is defined between all  
> > operators. If & had precedence defined only by comparison to other  
> > bitwise operators and / – 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems)  
> > with current operator definition syntax
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts)  
> > of operator definitions
> > 
> > Consider two operator definitions in different modules.
> > 
> > Module A:
> > 
> > infix operator |\> { precedence 137 associativity left }
> > 
> > Module B:
> > 
> > infix operator |\> { precedence 138 associativity left }
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed)  
> > solution  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change)  
> > syntax for operator definition
> > 
> > #operator(\<\>, fixity: infix, associativity: left)  
> > #operator(!, fixity: postfix)
> > 
> > First parameter of #operator directive is name of the operator. Then goes  
> > required parameter fixity that can be infix,prefix, or postfix. Then, for  
> > infix operators, goes optional associativity parameter that can be left  
> > or right.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative)  
> > precedence
> > 
> > Remove precedence property from operator definitions. Instead, introduce  
> > #precedence directive:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(\*, equalTo: /)
> > 
> > Omission of parentheses is allowed only when precedence between the two  
> > operators is defined.
> > 
> > 1 + 2 \* 3 // ok1 + 2 - 3 // error!  
> > #precedence(-, equalTo: +)1 + 2 - 3 // now ok
> > 
> > Precedence equality can only be defined for operators with same  
> > associativity.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict)  
> > resolution
> > 
> > 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:
> > 
> > #precedence(\*, lessThan: +) // error, previously defined `+` \< `*`
> > 
> > Operator definitions do nut cause conflicts, unless they are infix and  
> > one of them has associativity: left, but another one has associativity:  
> > right.
> > 
> > #operator(!, fixity: prefix) // ok, duplicated definitions  
> > #operator(\<\>, fixity: infix)  
> > #operator(\<\>, fixity: infix, associativity: left) // ok, now left associative  
> > #operator(+, fixity: infix, associativity: right) // error: associativity conflict
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed)  
> > design
> > 
> > operator keyword and local keywords associativity, precedence, left, right will  
> > be removed.
> > 
> > Directives with following (informal) syntax will be added:
> > 
> > #operator(OPERATOR\_NAME, fixity: FIXITY)  
> > #operator(OPERATOR\_NAME, fixity: infix, associativity: ASSOCIATIVITY)  
> > #precedence(OPERATOR\_NAME, lessThan: OPERATOR\_NAME)  
> > #precedence(OPERATOR\_NAME, equalTo: OPERATOR\_NAME)
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact)  
> > on existing code
> > 
> > Standard library operator declarations will need to be rewritten. Some of  
> > the existing precedence rules will need to be rewritten using #precedence  
> > directive.
> > 
> > More importantly, it needs to be discussed what operator precedence rules  
> > do \*not\* need to be retained.
> > 
> > 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.
> > 
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives)  
> > considered  
> > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave)  
> > current operator syntax (but change precedence)
> > 
> > #precedence 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:
> > 
> > prefix operator ! { }infix operator |\> { }infix operator \<\> { associativity left }
> > 
> > If body of operator can only contain associativity (in some cases), then  
> > the existence of body itself makes no sense.  
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![James\_Campbell](https://avatars.discourse-cdn.com/v4/letter/j/f19dbf/32.png) [@James\_Campbell](https://forums.swift.org/u/James_Campbell)\
**Post date:** [April 3, 2016, 11:38am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/11 "2016-04-03T11:38:15Z")

</div>

In these case of module operator conflicts perhaps there could be a way we  
could import these operators ?

Likes a #importOperators(OtherModule) or some kind of build flag.

> **···**
>
> \*\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\*
> 
> \*James⎥Future Prime Minister\*
> 
> \*james@supmenow.com \<james@supmenow.com\>⎥supmenow.com \<[http://supmenow.com](http://supmenow.com)\>\*
> 
> \*Sup\*
> 
> \*Runway East \*
> 
> \*10 Finsbury Square\*
> 
> \*London\*
> 
> \* EC2A 1AF \*
> 
> On Sun, Apr 3, 2016 at 12:26 PM, Ross O'Brien via swift-evolution \< swift-evolution@swift.org\> wrote:
> 
> > There is a problem here of duplicated operators or custom precedence, and  
> > how that gets passed between modules.  
> > 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).
> > 
> > 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?
> > 
> > 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 -\>  
> > 54)' then a #selector-like operator signature would come in really handy.
> > 
> > On Sun, Apr 3, 2016 at 12:10 PM, Taras Zakharko via swift-evolution \< \> swift-evolution@swift.org\> wrote:
> > 
> > > 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.
> > > 
> > > Maybe one should also have visibility for precedence, for instance having  
> > > precedence module-internal by default?
> > > 
> > > Best,
> > > 
> > > — Taras
> > > 
> > > On 03 Apr 2016, at 11:36, Антон Жилин via swift-evolution \< \>\> swift-evolution@swift.org\> wrote:
> > > 
> > > 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.
> > > 
> > > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > > 
> > > Introduction
> > > 
> > > Replace syntax of operator definition:
> > > 
> > > infix operator \<\> { precedence 100 associativity left }
> > > 
> > > With a directive:
> > > 
> > > #operator(\<\>, fixity: infix, associativity: left)
> > > 
> > > Also replace numeric definition of precedence with separate comparative  
> > > precedence definitions:
> > > 
> > > #precedence(+, lessThan: \*)  
> > > #precedence(+, equalTo: -)
> > > 
> > > Swift-evolution thread: link to the discussion thread for that proposal  
> > > \<[https://lists.swift.org/pipermail/swift-evolution&gt](https://lists.swift.org/pipermail/swift-evolution&gt);
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#motivation&gt);  
> > > Motivation  
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-numeric-definition-of-precedence&gt;Problems)  
> > > with numeric definition of precedence
> > > 
> > > In the beginning, operators had nice precedence values: 90, 100, 110,  
> > > 120, 130, 140, 150, 160.
> > > 
> > > 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, as got precedence 132. ?? had precedence greater than \<,  
> > > but less thanas, so it had to be given precedence 131.
> > > 
> > > Now it is not possible to insert any custom operator between \< and ??.  
> > > It is an inevitable consequence of current design: it will be impossible to  
> > > insert an operator between two existing ones at some point.
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-a-single-precedence-hierarchy&gt;Problems)  
> > > with a single precedence hierarchy
> > > 
> > > Currently, if an operator wants to define precedence by comparison to one  
> > > operator, it must do so for all other operators.
> > > 
> > > In many cases, this is not wished. Example: a & b \< c is a common error  
> > > pattern. a / b as Double is another one. C++ compilers sometimes emit  
> > > warnings on these. Swift does not.
> > > 
> > > The root of the problem is that precedence is defined between all  
> > > operators. If & had precedence defined only by comparison to other  
> > > bitwise operators and / – 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.
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#problems-with-current-operator-definition-syntax&gt;Problems)  
> > > with current operator definition syntax
> > > 
> > > 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.
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflicts-of-operator-definitions&gt;Conflicts)  
> > > of operator definitions
> > > 
> > > Consider two operator definitions in different modules.
> > > 
> > > Module A:
> > > 
> > > infix operator |\> { precedence 137 associativity left }
> > > 
> > > Module B:
> > > 
> > > infix operator |\> { precedence 138 associativity left }
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#proposed-solution&gt;Proposed)  
> > > solution  
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#change-syntax-for-operator-definition&gt;Change)  
> > > syntax for operator definition
> > > 
> > > #operator(\<\>, fixity: infix, associativity: left)  
> > > #operator(!, fixity: postfix)
> > > 
> > > First parameter of #operator directive is name of the operator. Then  
> > > goes required parameter fixity that can be infix,prefix, or postfix.  
> > > Then, for infix operators, goes optional associativity parameter that  
> > > can be left or right.
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#comparative-precedence&gt;Comparative)  
> > > precedence
> > > 
> > > Remove precedence property from operator definitions. Instead, introduce  
> > > #precedence directive:
> > > 
> > > #precedence(+, lessThan: \*)  
> > > #precedence(\*, equalTo: /)
> > > 
> > > Omission of parentheses is allowed only when precedence between the two  
> > > operators is defined.
> > > 
> > > 1 + 2 \* 3 // ok1 + 2 - 3 // error!  
> > > #precedence(-, equalTo: +)1 + 2 - 3 // now ok
> > > 
> > > Precedence equality can only be defined for operators with same  
> > > associativity.
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#conflict-resolution&gt;Conflict)  
> > > resolution
> > > 
> > > 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:
> > > 
> > > #precedence(\*, lessThan: +) // error, previously defined `+` \< `*`
> > > 
> > > Operator definitions do nut cause conflicts, unless they are infix and  
> > > one of them has associativity: left, but another one has associativity:  
> > > right.
> > > 
> > > #operator(!, fixity: prefix) // ok, duplicated definitions  
> > > #operator(\<\>, fixity: infix)  
> > > #operator(\<\>, fixity: infix, associativity: left) // ok, now left associative  
> > > #operator(+, fixity: infix, associativity: right) // error: associativity conflict
> > > 
> > > 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.
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#detailed-design&gt;Detailed)  
> > > design
> > > 
> > > operator keyword and local keywords associativity, precedence, left,  
> > > right will be removed.
> > > 
> > > Directives with following (informal) syntax will be added:
> > > 
> > > #operator(OPERATOR\_NAME, fixity: FIXITY)  
> > > #operator(OPERATOR\_NAME, fixity: infix, associativity: ASSOCIATIVITY)  
> > > #precedence(OPERATOR\_NAME, lessThan: OPERATOR\_NAME)  
> > > #precedence(OPERATOR\_NAME, equalTo: OPERATOR\_NAME)
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#impact-on-existing-code&gt;Impact)  
> > > on existing code
> > > 
> > > Standard library operator declarations will need to be rewritten. Some of  
> > > the existing precedence rules will need to be rewritten using #precedence  
> > > directive.
> > > 
> > > More importantly, it needs to be discussed what operator precedence rules  
> > > do \*not\* need to be retained.
> > > 
> > > 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.
> > > 
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#alternatives-considered&gt;Alternatives)  
> > > considered  
> > > \<[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md#leave-current-operator-syntax-but-change-precedence&gt;Leave)  
> > > current operator syntax (but change precedence)
> > > 
> > > #precedence 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:
> > > 
> > > prefix operator ! { }infix operator |\> { }infix operator \<\> { associativity left }
> > > 
> > > If body of operator can only contain associativity (in some cases), then  
> > > the existence of body itself makes no sense.  
> > > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > > swift-evolution mailing list  
> > > swift-evolution@swift.org  
> > > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)
> > > 
> > > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > > swift-evolution mailing list  
> > > swift-evolution@swift.org  
> > > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [April 3, 2016, 12:13pm UTC](https://forums.swift.org/t/proposal-custom-operators/2046/12 "2016-04-03T12:13:16Z")

</div>

Right, the proposal in its current form does not really aim to resolve such  
conflicts, although it makes them occur less often by "merging" precedence  
and associativity when possible.

At first, I also tried to resolve such conflicts by naming operators. But I  
found that compiler instructions will be too complex in some cases:

#operator(+, name: numericAdd, fixity: infix, associativity: left)  
#operator(+, name: arrayAppend, fixity: infix, associativity: right)

func numericAdd(left: A, right: B) -\> C  
func numericAdd(left: B, right: C) -\> B  
func arrayAppend(left: A, right: A) -\> B  
func arrayAppend(left: B, right: C) -\> A

A() + B() + C()

Compiler will have to find by brute-force that this expression can only  
represent arrayAppend(A(), arrayAppend(B(), C())), and others result in  
errors. To me, this scheme seems pretty absurd.

That said, it might be a good idea to add visibility for operators.  
Hiding already imported operators, on the other hand, would be inconsistent  
with othr elements of the language. It is currently impossible to hide  
contents of module A from C where C imports B and B imports A. Not that I'm  
against such a feature in general.

- Anton

> **···**
>
> 2016-04-03 14:26 GMT+03:00 Ross O'Brien \<narrativium+swift@gmail.com\>:
> 
> > There is a problem here of duplicated operators or custom precedence, and  
> > how that gets passed between modules.  
> > 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).
> > 
> > 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?
> > 
> > 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 -\>  
> > 54)' then a #selector-like operator signature would come in really handy.

---

<div class="post-metadata">

**Author:** ![Qbyte](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/qbyte/32/362_2.png) [@Qbyte](https://forums.swift.org/u/Qbyte)\
**Post date:** [April 4, 2016, 5:06am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/13 "2016-04-04T05:06:07Z")

</div>

See inline

> There is a problem here of duplicated operators or custom precedence, and how that gets passed between modules.  
> 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).
> 
> 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?

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.

@AHTOH  
Why do you use #keyword ?  
I think defining a operator with

&nbsp;&nbsp;&nbsp;&nbsp;infix operator + {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
&nbsp;&nbsp;&nbsp;&nbsp;}

is perfectly fine since it is similar to class/struct/enum declaration.

&nbsp;&nbsp;&nbsp;&nbsp;// and it's precedence  
&nbsp;&nbsp;&nbsp;&nbsp;precedence(+ lessThan \*)

Note the missing "," and ":" before and after "lessThan" in order to give both operators the same importance (minor issue).

I feel that

&nbsp;&nbsp;&nbsp;&nbsp;#precedence(+, lessThan: \*)

puts too much importance on the first operator.

Best regards  
- Maximilian

> **···**
>
> > Am 03.04.2016 um 13:26 schrieb Ross O'Brien via swift-evolution \<swift-evolution@swift.org\>:
> 
> > 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 -\> 54)' then a #selector-like operator signature would come in really handy.
> > 
> > > On Sun, Apr 3, 2016 at 12:10 PM, Taras Zakharko via swift-evolution \<swift-evolution@swift.org\> wrote:  
> > > 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.
> > > 
> > > Maybe one should also have visibility for precedence, for instance having precedence module-internal by default?
> > > 
> > > Best,
> > > 
> > > — Taras
> > > 
> > > > On 03 Apr 2016, at 11:36, Антон Жилин via swift-evolution \<swift-evolution@swift.org\> wrote:
> > > > 
> > > > 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.
> > > > 
> > > > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > > > 
> > > > Introduction
> > > > 
> > > > Replace syntax of operator definition:
> > > > 
> > > > infix operator \<\> { precedence 100 associativity left }  
> > > > With a directive:
> > > > 
> > > > #operator(\<\>, fixity: infix, associativity: left)  
> > > > Also replace numeric definition of precedence with separate comparative precedence definitions:
> > > > 
> > > > #precedence(+, lessThan: \*)  
> > > > #precedence(+, equalTo: -)  
> > > > Swift-evolution thread: link to the discussion thread for that proposal
> > > > 
> > > > Motivation
> > > > 
> > > > Problems with numeric definition of precedence
> > > > 
> > > > In the beginning, operators had nice precedence values: 90, 100, 110, 120, 130, 140, 150, 160.
> > > > 
> > > > 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, as got precedence 132. ?? had precedence greater than \<, but less thanas, so it had to be given precedence 131.
> > > > 
> > > > Now it is not possible to insert any custom operator between \< and ??. It is an inevitable consequence of current design: it will be impossible to insert an operator between two existing ones at some point.
> > > > 
> > > > Problems with a single precedence hierarchy
> > > > 
> > > > Currently, if an operator wants to define precedence by comparison to one operator, it must do so for all other operators.
> > > > 
> > > > In many cases, this is not wished. Example: a & b \< c is a common error pattern. a / b as Double is another one. C++ compilers sometimes emit warnings on these. Swift does not.
> > > > 
> > > > The root of the problem is that precedence is defined between all operators. If & had precedence defined only by comparison to other bitwise operators and / – 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.
> > > > 
> > > > Problems with current operator definition syntax
> > > > 
> > > > 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.
> > > > 
> > > > Conflicts of operator definitions
> > > > 
> > > > Consider two operator definitions in different modules.
> > > > 
> > > > Module A:
> > > > 
> > > > infix operator |\> { precedence 137 associativity left }  
> > > > Module B:
> > > > 
> > > > infix operator |\> { precedence 138 associativity left }  
> > > > Proposed solution
> > > > 
> > > > Change syntax for operator definition
> > > > 
> > > > #operator(\<\>, fixity: infix, associativity: left)  
> > > > #operator(!, fixity: postfix)  
> > > > First parameter of #operator directive is name of the operator. Then goes required parameter fixity that can be infix,prefix, or postfix. Then, for infix operators, goes optional associativity parameter that can be left or right.
> > > > 
> > > > Comparative precedence
> > > > 
> > > > Remove precedence property from operator definitions. Instead, introduce #precedence directive:
> > > > 
> > > > #precedence(+, lessThan: \*)  
> > > > #precedence(\*, equalTo: /)  
> > > > Omission of parentheses is allowed only when precedence between the two operators is defined.
> > > > 
> > > > 1 + 2 \* 3 // ok  
> > > > 1 + 2 - 3 // error!  
> > > > #precedence(-, equalTo: +)  
> > > > 1 + 2 - 3 // now ok  
> > > > Precedence equality can only be defined for operators with same associativity.
> > > > 
> > > > Conflict resolution
> > > > 
> > > > 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:
> > > > 
> > > > #precedence(\*, lessThan: +) // error, previously defined `+` \< `*`  
> > > > Operator definitions do nut cause conflicts, unless they are infix and one of them has associativity: left, but another one has associativity: right.
> > > > 
> > > > #operator(!, fixity: prefix) // ok, duplicated definitions  
> > > > #operator(\<\>, fixity: infix)  
> > > > #operator(\<\>, fixity: infix, associativity: left) // ok, now left associative  
> > > > #operator(+, fixity: infix, associativity: right) // error: associativity conflict  
> > > > 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.
> > > > 
> > > > Detailed design
> > > > 
> > > > operator keyword and local keywords associativity, precedence, left, right will be removed.
> > > > 
> > > > Directives with following (informal) syntax will be added:
> > > > 
> > > > #operator(OPERATOR\_NAME, fixity: FIXITY)  
> > > > #operator(OPERATOR\_NAME, fixity: infix, associativity: ASSOCIATIVITY)  
> > > > #precedence(OPERATOR\_NAME, lessThan: OPERATOR\_NAME)  
> > > > #precedence(OPERATOR\_NAME, equalTo: OPERATOR\_NAME)  
> > > > Impact on existing code
> > > > 
> > > > Standard library operator declarations will need to be rewritten. Some of the existing precedence rules will need to be rewritten using #precedence directive.
> > > > 
> > > > More importantly, it needs to be discussed what operator precedence rules do not need to be retained.
> > > > 
> > > > 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.
> > > > 
> > > > Alternatives considered
> > > > 
> > > > Leave current operator syntax (but change precedence)
> > > > 
> > > > #precedence 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:
> > > > 
> > > > prefix operator ! { }  
> > > > infix operator |\> { }  
> > > > infix operator \<\> { associativity left }  
> > > > If body of operator can only contain associativity (in some cases), then the existence of body itself makes no sense.  
> > > > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > > > swift-evolution mailing list  
> > > > swift-evolution@swift.org  
> > > > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)
> > > 
> > > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > > swift-evolution mailing list  
> > > swift-evolution@swift.org  
> > > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [April 4, 2016, 6:49am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/14 "2016-04-04T06:49:27Z")

</div>

In the poposed model, all relations are not transitive. Example:

#precedence(+, lessThan: \*)  
#precedence(\*, lessThan: ^)  
1 ^ 2 + 3 // error  
#precedence(+, lessThan: ^)  
1 ^ 2 + 3 // now ok

Would it be better to have such indirect relations inferred? Or would it  
put too much responsibility on the compiler?  
Maybe add it to future directions?

Cycles of length \>2 are also allowed. This was not added intentionally, but  
follows from other specified rules.  
Example: ^ (binary) \< & (binary) \< + \< \* \< ^ (power). OK, & \< + is a bit  
stretched, otherwise quite logical.

> - I wonder if there are cases in the standard operators which would be

better modeled as a non-linear chain.  
In the standard library, non-linearity will be primarily used to break a  
single hierarchy into multiple small ones. I doubt that any trees or cycles  
will form, although that would be good news.

- Anton

> **···**
>
> 2016-04-04 8:55 GMT+03:00 David Waite \<david@alkaline-solutions.com\>:
> 
> > Interesting model!
> > 
> > If I understand correctly: this changes the precedence from being based on  
> > a numeric value, to being represented as a bit of a DAG of precedence  
> > groups. A precedence group is defined implicitly for each operator, with  
> > one group around each set of operators where equalTo has been declared.
> > 
> > The groups are lazily evaluated, so if an expression can be resolved  
> > without ambiguity due to lack of reachability between two individual  
> > operators in the DAG, there is no issue/error.
> > 
> > Comments:  
> > - I wonder if there are cases in the standard operators which would be  
> > better modeled as a non-linear chain. The compiler could warn around usage  
> > which is defined by operator precedence, but is commonly considered  
> > ambiguous or error prone.
> > 
> > For example, if users commonly get confused about the conjunctive and  
> > disjunctive levels (logical ‘and’ and ‘or’) being different levels with  
> > precedence, you could just omit the lessThan relationship between the two  
> > of them. The compiler would then error on ambiguous cases, prompting the  
> > user to use parenthesis.
> > 
> > - I’d prefer instead of operator precedence groups just being implicit by  
> > use of #precedence equalTo, that the operators are bound to a group  
> > explicitly. Something like  
> > #precedence(+, group: “additive”)  
> > #precedence(“additive”, lessThan: “multiplicative”)
> > 
> > However, this may create more issues than it solves (two frameworks  
> > creating their own custom operators, putting them in custom precedence  
> > groups, and the consumer decides the two precedence groups are really  
> > equivalent)
> > 
> > -DW
> > 
> > On Apr 3, 2016, at 3:36 AM, Антон Жилин via swift-evolution \< \> swift-evolution@swift.org\> wrote:
> > 
> > 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.
> > 
> > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)

---

<div class="post-metadata">

**Author:** ![Rainer\_Brockerhoff](https://avatars.discourse-cdn.com/v4/letter/r/65b543/32.png) [@Rainer\_Brockerhoff](https://forums.swift.org/u/Rainer_Brockerhoff)\
**Post date:** [April 6, 2016, 12:34pm UTC](https://forums.swift.org/t/proposal-custom-operators/2046/15 "2016-04-06T12:34:08Z")

</div>

Quoting the book:  
“Swift’s operator precedences and associativity rules are simpler and  
more predictable than those found in C and Objective-C. ”  
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.2  
Prerelease).” iBooks.

A word of caution. I've been programming since 1969 (and this does  
include languages like PL/I and B6700 ALGOL, for instance). For the past  
35 years or so, mostly C and Objective-C. Nevertheless I've been bitten  
far too often by misremembering operator precedences — and I refuse to  
tack the rules up on my wall, or print them upside down on my t-shirt.

With advancing experience, as complexity increases and available neurons  
decrease, I find myself \_always\_ using parentheses, or even intermediate  
variables. It looks unwieldy but it's easier to reason about and to  
debug. Why should I have to remember what `a && b || c` means in  
practice in a particular language?

With newly-declared operators (especially not newly-declared by ME!) the  
potential for confusion becomes ever-higher.

I caution against proposals that allow excess flexibility in defining  
operator precedence. Even the existing numerical precedence values can  
be abused, and expanding them by using some sort of tree, or (say)  
floating-point values, is just a "foolish consistency".

I'd say, have the established precedence groups defined by name, and  
allow adding new operators to only some of these groups. Inside those,  
group by associativity - perhaps the few right-associative types should  
not allow any new operators to be added.

All IMHO of course.

> **···**
>
> On 4/4/16 15:21, Daniel Duan via swift-evolution wrote:
> 
> > > Антон Жилин via swift-evolution \<swift-evolution@...\> writes:
> > > 
> > > 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.
> > 
> > ...[snip]
> > 
> > 3. It may be a good exercise to work out how would each of the builtin  
> > &nbsp;&nbsp;&nbsp;&nbsp;operators would be defined with this change and mention it (not the entire  
> > &nbsp;&nbsp;&nbsp;&nbsp;definition, but the fact that it's possible, or reasons why it produces  
> > &nbsp;&nbsp;&nbsp;&nbsp;any difference) in the proposal.
> 
> --  
> Rainer Brockerhoff \<rainer@brockerhoff.net\>  
> Belo Horizonte, Brazil  
> "In the affairs of others even fools are wise  
> In their own business even sages err."
> 
> > **[Solipsism Gradient](https://brockerhoff.net/blog/)**
> >
> > Rainer Brockerhoff’s blog

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [April 4, 2016, 6:06am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/16 "2016-04-04T06:06:47Z")

</div>

Thank you for a helpful answer!  
I like the idea of overriding precedence from another module. We won't need  
to introduce additional keywords or visibility for operators. I will add it  
to the proposal.

I assume you mean precedence inside braces of operator, then operator scope  
makes sense. Self operator could be omit as well, following the idea that  
we are introducing a new operator and want to compare it to others:

infix operator \* {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
&nbsp;&nbsp;&nbsp;&nbsp;precedenceLess: ^  
&nbsp;&nbsp;&nbsp;&nbsp;precedenceEqual: /  
&nbsp;&nbsp;&nbsp;&nbsp;precedenceGreater: +  
}  
infix operator / {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
&nbsp;&nbsp;&nbsp;&nbsp;precedenceLess: ^  
&nbsp;&nbsp;&nbsp;&nbsp;precedenceEqual: \*  
&nbsp;&nbsp;&nbsp;&nbsp;precedenceGreater: +  
}

Equivalent precedence rules would be allowed for symmetry in the operator  
definitions.  
We would still be able to reopen the scope and add precedence and  
associativity rules.  
I agree that this scheme has advantage of being a smaller change.

I'm still concerned about syntax.  
Is it OK to have "less, equal, greater" in precedence name?  
Is it OK to have both curly brackets and dictionary syntax (a precedent, I  
guess)?  
Is it OK to leave prefix and postfix operators always with empty braces?

Would it be better to have multiple precedence comparisons at once:  
precedenceGreater: +, -, \*, /  
Or one comparison per line will be more readable?

I will add this to alternatives, but will not swap it with currently stated  
syntax for now, waiting for some more response.

What do you think?

- Anton

> **···**
>
> 2016-04-04 8:06 GMT+03:00 Maximilian Hünenberger \<m.huenenberger@me.com\>:
> 
> > See inline
> > 
> > Am 03.04.2016 um 13:26 schrieb Ross O'Brien via swift-evolution \< \> swift-evolution@swift.org\>:
> > 
> > There is a problem here of duplicated operators or custom precedence, and  
> > how that gets passed between modules.  
> > 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).
> > 
> > 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?
> > 
> > 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.
> > 
> > @AHTOH  
> > Why do you use #keyword ?  
> > I think defining a operator with
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;infix operator + {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
> > &nbsp;&nbsp;&nbsp;&nbsp;}
> > 
> > is perfectly fine since it is similar to class/struct/enum declaration.
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;// and it's precedence  
> > &nbsp;&nbsp;&nbsp;&nbsp;precedence(+ lessThan \*)
> > 
> > Note the missing "," and ":" before and after "lessThan" in order to give  
> > both operators the same importance (minor issue).
> > 
> > I feel that
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;#precedence(+, lessThan: \*)
> > 
> > puts too much importance on the first operator.
> > 
> > Best regards  
> > - Maximilian
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Ross\_O\_Brien](https://avatars.discourse-cdn.com/v4/letter/r/e56c9b/32.png) [@Ross\_O\_Brien](https://forums.swift.org/u/Ross_O_Brien)\
**Post date:** [April 4, 2016, 10:08am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/17 "2016-04-04T10:08:38Z")

</div>

How is a non-transitive relation different from a conflict?  
If we use:  
#precedence(+, lessThan: \*)  
#precedence(\*, lessThan: ^)  
#precedence(^, lessThan: +)  
Surely that should be an error, even with none of the operators actually  
used?

The compiler would be asked to verify two things: that the relationships of  
all operators in the program can be expressed with a topological ordering,  
and any pair of operators used together in an expression in the program has  
an unambiguous precedence in that ordering. (I have no idea how relatable  
this comparison actually is, but it seems like it would be a simpler  
problem than analysing NSLayoutConstraints for violations.)

> **···**
>
> On Mon, Apr 4, 2016 at 7:49 AM, Антон Жилин \<swift-evolution@swift.org\> wrote:
> 
> > In the poposed model, all relations are not transitive. Example:
> > 
> > #precedence(+, lessThan: \*)  
> > #precedence(\*, lessThan: ^)  
> > 1 ^ 2 + 3 // error  
> > #precedence(+, lessThan: ^)  
> > 1 ^ 2 + 3 // now ok
> > 
> > Would it be better to have such indirect relations inferred? Or would it  
> > put too much responsibility on the compiler?  
> > Maybe add it to future directions?
> > 
> > Cycles of length \>2 are also allowed. This was not added intentionally,  
> > but follows from other specified rules.  
> > Example: ^ (binary) \< & (binary) \< + \< \* \< ^ (power). OK, & \< + is a bit  
> > stretched, otherwise quite logical.
> > 
> > \> - I wonder if there are cases in the standard operators which would be  
> > better modeled as a non-linear chain.  
> > In the standard library, non-linearity will be primarily used to break a  
> > single hierarchy into multiple small ones. I doubt that any trees or cycles  
> > will form, although that would be good news.
> > 
> > - Anton
> > 
> > 2016-04-04 8:55 GMT+03:00 David Waite \<david@alkaline-solutions.com\>:
> > 
> > > Interesting model!
> > > 
> > > If I understand correctly: this changes the precedence from being based  
> > > on a numeric value, to being represented as a bit of a DAG of precedence  
> > > groups. A precedence group is defined implicitly for each operator, with  
> > > one group around each set of operators where equalTo has been declared.
> > > 
> > > The groups are lazily evaluated, so if an expression can be resolved  
> > > without ambiguity due to lack of reachability between two individual  
> > > operators in the DAG, there is no issue/error.
> > > 
> > > Comments:  
> > > - I wonder if there are cases in the standard operators which would be  
> > > better modeled as a non-linear chain. The compiler could warn around usage  
> > > which is defined by operator precedence, but is commonly considered  
> > > ambiguous or error prone.
> > > 
> > > For example, if users commonly get confused about the conjunctive and  
> > > disjunctive levels (logical ‘and’ and ‘or’) being different levels with  
> > > precedence, you could just omit the lessThan relationship between the two  
> > > of them. The compiler would then error on ambiguous cases, prompting the  
> > > user to use parenthesis.
> > > 
> > > - I’d prefer instead of operator precedence groups just being implicit by  
> > > use of #precedence equalTo, that the operators are bound to a group  
> > > explicitly. Something like  
> > > #precedence(+, group: “additive”)  
> > > #precedence(“additive”, lessThan: “multiplicative”)
> > > 
> > > However, this may create more issues than it solves (two frameworks  
> > > creating their own custom operators, putting them in custom precedence  
> > > groups, and the consumer decides the two precedence groups are really  
> > > equivalent)
> > > 
> > > -DW
> > > 
> > > On Apr 3, 2016, at 3:36 AM, Антон Жилин via swift-evolution \< \>\> swift-evolution@swift.org\> wrote:
> > > 
> > > 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.
> > > 
> > > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [April 4, 2016, 10:41am UTC](https://forums.swift.org/t/proposal-custom-operators/2046/18 "2016-04-04T10:41:22Z")

</div>

Just to clarify, with currently proposed  
behaviour, corresponding expressions would be parsed as follows:

a + b \* c // a + (b \* c)  
a \* b ^ c // a \* (b ^ c)  
a ^ b + c // a ^ (b + c)

The compiler would look only at explicitly stated precedence between two  
given operators and would not try to use transcendency.

Having said that, at least two opinions were that operators should form a  
DAG by precedence. If no objections are stated, I will change the proposal  
accordingly, also without future directions.

On, Apr 4, 2016, Ross O'Brien wrote:

> **···**
>
> > How is a non-transitive relation different from a conflict?  
> > If we use:  
> > #precedence(+, lessThan: \*)  
> > #precedence(\*, lessThan: ^)  
> > #precedence(^, lessThan: +)  
> > Surely that should be an error, even with none of the operators actually  
> > used?
> > 
> > The compiler would be asked to verify two things: that the relationships  
> > of all operators in the program can be expressed with a topological  
> > ordering, and any pair of operators used together in an expression in the  
> > program has an unambiguous precedence in that ordering. (I have no idea how  
> > relatable this comparison actually is, but it seems like it would be a  
> > simpler problem than analysing NSLayoutConstraints for violations.)
> > 
> > On Mon, Apr 4, 2016 at 7:49 AM, Антон Жилин \<swift-evolution@swift.org\> \> wrote:
> > 
> > > In the poposed model, all relations are not transitive. Example:
> > > 
> > > #precedence(+, lessThan: \*)  
> > > #precedence(\*, lessThan: ^)  
> > > 1 ^ 2 + 3 // error  
> > > #precedence(+, lessThan: ^)  
> > > 1 ^ 2 + 3 // now ok
> > > 
> > > Would it be better to have such indirect relations inferred? Or would it  
> > > put too much responsibility on the compiler?  
> > > Maybe add it to future directions?
> > > 
> > > Cycles of length \>2 are also allowed. This was not added intentionally,  
> > > but follows from other specified rules.  
> > > Example: ^ (binary) \< & (binary) \< + \< \* \< ^ (power). OK, & \< + is a bit  
> > > stretched, otherwise quite logical.
> > > 
> > > \> - I wonder if there are cases in the standard operators which would be  
> > > better modeled as a non-linear chain.  
> > > In the standard library, non-linearity will be primarily used to break a  
> > > single hierarchy into multiple small ones. I doubt that any trees or cycles  
> > > will form, although that would be good news.
> > > 
> > > - Anton
> > > 
> > > 2016-04-04 8:55 GMT+03:00 David Waite \<david@alkaline-solutions.com\>:
> > > 
> > > > Interesting model!
> > > > 
> > > > If I understand correctly: this changes the precedence from being based  
> > > > on a numeric value, to being represented as a bit of a DAG of precedence  
> > > > groups. A precedence group is defined implicitly for each operator, with  
> > > > one group around each set of operators where equalTo has been declared.
> > > > 
> > > > The groups are lazily evaluated, so if an expression can be resolved  
> > > > without ambiguity due to lack of reachability between two individual  
> > > > operators in the DAG, there is no issue/error.
> > > > 
> > > > Comments:  
> > > > - I wonder if there are cases in the standard operators which would be  
> > > > better modeled as a non-linear chain. The compiler could warn around usage  
> > > > which is defined by operator precedence, but is commonly considered  
> > > > ambiguous or error prone.
> > > > 
> > > > For example, if users commonly get confused about the conjunctive and  
> > > > disjunctive levels (logical ‘and’ and ‘or’) being different levels with  
> > > > precedence, you could just omit the lessThan relationship between the two  
> > > > of them. The compiler would then error on ambiguous cases, prompting the  
> > > > user to use parenthesis.
> > > > 
> > > > - I’d prefer instead of operator precedence groups just being implicit  
> > > > by use of #precedence equalTo, that the operators are bound to a group  
> > > > explicitly. Something like  
> > > > #precedence(+, group: “additive”)  
> > > > #precedence(“additive”, lessThan: “multiplicative”)
> > > > 
> > > > However, this may create more issues than it solves (two frameworks  
> > > > creating their own custom operators, putting them in custom precedence  
> > > > groups, and the consumer decides the two precedence groups are really  
> > > > equivalent)
> > > > 
> > > > -DW
> > > > 
> > > > On Apr 3, 2016, at 3:36 AM, Антон Жилин via swift-evolution \< \>\>\> swift-evolution@swift.org\> wrote:
> > > > 
> > > > 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.
> > > > 
> > > > [https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)
> > > 
> > > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > > swift-evolution mailing list  
> > > swift-evolution@swift.org  
> > > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Qbyte](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/qbyte/32/362_2.png) [@Qbyte](https://forums.swift.org/u/Qbyte)\
**Post date:** [April 4, 2016, 9:14pm UTC](https://forums.swift.org/t/proposal-custom-operators/2046/19 "2016-04-04T21:14:30Z")

</div>

Inline

> Thank you for a helpful answer!  
> I like the idea of overriding precedence from another module. We won't need to introduce additional keywords or visibility for operators. I will add it to the proposal.
> 
> I assume you mean precedence inside braces of operator, then operator scope makes sense. Self operator could be omit as well, following the idea that we are introducing a new operator and want to compare it to others:
> 
> infix operator \* {  
> &nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
> &nbsp;&nbsp;&nbsp;&nbsp;precedenceLess: ^  
> &nbsp;&nbsp;&nbsp;&nbsp;precedenceEqual: /  
> &nbsp;&nbsp;&nbsp;&nbsp;precedenceGreater: +  
> }  
> infix operator / {  
> &nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
> &nbsp;&nbsp;&nbsp;&nbsp;precedenceLess: ^  
> &nbsp;&nbsp;&nbsp;&nbsp;precedenceEqual: \*  
> &nbsp;&nbsp;&nbsp;&nbsp;precedenceGreater: +  
> }
> 
> Equivalent precedence rules would be allowed for symmetry in the operator definitions.  
> We would still be able to reopen the scope and add precedence and associativity rules.  
> I agree that this scheme has advantage of being a smaller change.
> 
> I'm still concerned about syntax.  
> Is it OK to have "less, equal, greater" in precedence name?

What do you mean by OK? Other operators like == are weird:

precedence(== == \<)  
// in comparison to  
precedence(== equalTo \<)

> Is it OK to have both curly brackets and dictionary syntax (a precedent, I guess)?

That could be a consistency problem. However I'd like to keep a declaration syntax instead of defining operators through compiler directives.

> Is it OK to leave prefix and postfix operators always with empty braces?

I'm fine with that.

> Would it be better to have multiple precedence comparisons at once:  
> precedenceGreater: +, -, \*, /  
> Or one comparison per line will be more readable?
> 
> I will add this to alternatives, but will not swap it with currently stated syntax for now, waiting for some more response.
> 
> What do you think?
> 
> - Anton

After thinking more about it I came to the conclusion that we should have something like "precedence groups" where all operators have the same precedence:

precedenceGroup Additive {  
&nbsp;&nbsp;&nbsp;&nbsp;+, -  
}

precedenceGroup Multiplicative {  
&nbsp;&nbsp;&nbsp;&nbsp;\*, /  
}

// first we could allow an operator to be only  
// in one p.Group. Later when we can infer  
// precedences we can allow operators to be  
// in more than one p.Group (if that is even necessary)

// precedence declaration  
precedence(Additive lessThan Multiplicative)

// precedence declarations take  
// "precedenceGroup"s and "operator"s.

// It could also work with extensions so you  
// can easily insert it in the precedence hierarchy:

infix operator +- {  
&nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
}

// more operator declarations ...

extension Additive {  
&nbsp;&nbsp;&nbsp;&nbsp;+-, -+, ++, --  
}

// the syntax I used is highly discussable.  
// this should mainly be a concept suggestion.  
// I think it allows for greater flexibility since you can define  
// operator precedences much easier.

With kind regards  
- Maximilian

> **···**
>
> > Am 04.04.2016 um 08:06 schrieb Антон Жилин \<antonyzhilin@gmail.com\>:
> > 
> > 2016-04-04 8:06 GMT+03:00 Maximilian Hünenberger \<m.huenenberger@me.com\>:
> > 
> > > See inline
> > > 
> > > > Am 03.04.2016 um 13:26 schrieb Ross O'Brien via swift-evolution \<swift-evolution@swift.org\>:
> > > > 
> > > > There is a problem here of duplicated operators or custom precedence, and how that gets passed between modules.  
> > > > 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).
> > > > 
> > > > 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?
> > > 
> > > 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.
> > > 
> > > @AHTOH  
> > > Why do you use #keyword ?  
> > > I think defining a operator with
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;infix operator + {  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;associativity: left  
> > > &nbsp;&nbsp;&nbsp;&nbsp;}
> > > 
> > > is perfectly fine since it is similar to class/struct/enum declaration.
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;// and it's precedence  
> > > &nbsp;&nbsp;&nbsp;&nbsp;precedence(+ lessThan \*)
> > > 
> > > Note the missing "," and ":" before and after "lessThan" in order to give both operators the same importance (minor issue).
> > > 
> > > I feel that
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;#precedence(+, lessThan: \*)
> > > 
> > > puts too much importance on the first operator.
> > > 
> > > Best regards  
> > > - Maximilian
> > > 
> > > > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > > > swift-evolution mailing list  
> > > > swift-evolution@swift.org  
> > > > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [April 4, 2016, 9:40pm UTC](https://forums.swift.org/t/proposal-custom-operators/2046/20 "2016-04-04T21:40:42Z")

</div>

Sorry for breaking the thread, next time please mail me a copy :)  
Link to the proposal:  
[https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md](https://github.com/Anton3/swift-evolution/blob/operator-precedence/proposals/NNNN-operator-precedence.md)

1. I strongly agree that the numeric precedence system is not great. From

> &nbsp;&nbsp;&nbsp;&nbsp;a implementation point of view, the way to specify them in your  
> proposal  
> &nbsp;&nbsp;&nbsp;&nbsp;essentially gave all visible operators a partial order, in which we can  
> &nbsp;&nbsp;&nbsp;&nbsp;draw a directed gragh with operators being the nodes and their relation  
> &nbsp;&nbsp;&nbsp;&nbsp;being arcs. A part of the graph might look like: '^' --\> '\*' --\> '+',  
> the  
> &nbsp;&nbsp;&nbsp;&nbsp;nodes being the math operators. We can tell '\*' has a higher precedence  
> &nbsp;&nbsp;&nbsp;&nbsp;than '+', '^' has a higher precedence than '\*' and '+', by follwing the  
> &nbsp;&nbsp;&nbsp;&nbsp;arcs. If one operator is not reachable from another, and vice versa,  
> then  
> &nbsp;&nbsp;&nbsp;&nbsp;composing these two is illegal. We need to teach the compiler this  
> concept.

Right, that semantics was actually the main driver of the proposal.

2. Currently, it's not possible to specify precedence for pre- and postfix

> &nbsp;&nbsp;&nbsp;&nbsp;operators. Chris Lattner has mentioned that the  
> &nbsp;&nbsp;&nbsp;&nbsp;following result is not desirable:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;∆x + y  
> &nbsp;&nbsp;&nbsp;&nbsp;… where ∆ has a lower precendence than + while it's required to have no  
> &nbsp;&nbsp;&nbsp;&nbsp;space between ∆ and the operand. My understanding is that if spaces  
> were  
> &nbsp;&nbsp;&nbsp;&nbsp;to be allowed here, parsing such expression without ambiguity is a  
> &nbsp;&nbsp;&nbsp;&nbsp;non-trivial challenge. So, will it be possible to specify precedence  
> for  
> &nbsp;&nbsp;&nbsp;&nbsp;pre/postfix operators under your proposal?

No, I currently leave prefix and postfix operators unchanged (apart from  
syntax shuffling). I will add this as a future direction.  
Prefix and postfix operators would behave the same as infix, but have  
higher precedence than any infix operator by default.  
This feature, if added, would be non-breaking.

> 3. It may be a good exercise to work out how would each of the builtin  
> &nbsp;&nbsp;&nbsp;&nbsp;operators would be defined with this change and mention it (not the  
> entire  
> &nbsp;&nbsp;&nbsp;&nbsp;definition, but the fact that it's possible, or reasons why it produces  
> &nbsp;&nbsp;&nbsp;&nbsp;any difference) in the proposal.

Operators `is`, `as`, `as?`, `as!`, which are not actually Swift custom  
operators (they contain letters), will not participate in this exercise.  
(Let's not discuss allowing letters in operators here.)  
That being said, great idea. I will add example declarations of standard  
library operators.

- Anton

[Next page](https://forums.swift.org/t/proposal-custom-operators/2046.md?page=2)
