[swift-evolution] [Draft] Resolving operator precedence conflicts

Charles Kissinger crk at akkyra.com
Wed Mar 9 13:07:06 CST 2016


Anton,

Could your idea be simplified by having an operator attribute that applies only to the following function declaration rather than referring to one by name?

#operator(fixity: infix, associativity: left)
func +(left: Int, _ right: Int) -> Int

#operator(fixity: prefix)
func +(right: Int) -> Int


—CK

> On Mar 8, 2016, at 12:13 PM, Антон Жилин via swift-evolution <swift-evolution at swift.org> wrote:
> 
> There have been complaints on current syntax of operator declarations:
> 
> infix operator <> { associativity left precedence 100 assignment }
> 
> It looks like a collection of random words. Dictionary syntax would suit better here. Additionally, `assignment` has been deprecated for a long time, but not removed.
> 
> Many syntaxes were suggested. For example:
> 
> #operator(<>, fixity: infix, associativity: left, precedence: 100)
> 
> *But* Joe Groff uncovered a deeper problem. Current operators cannot be given precedence and associativity per concrete operator function.
> 
> Moreover, it makes more sense for operators to only allow parenthesis omission for some other operators. (C/C++ gives warnings for relying on precedence for unrelated operators.) 
> 
> Operator declarations may lie in different modules and not know anything about each other, but they will create a conflict if their names happen to be identical.
> 
> The following is my attempt at solving the problem.
> 
> 1.
> All operators are aliases for functions.
> 
> #operator(+, name: numericAdd, fixity: infix, associativity: left)
> 
> func numericAdd(left: Int, _ right: Int) -> Int
> 
> #operator(+, name: numericUnaryPlus, fixity: prefix)
> 
> func unaryPlus(right: Int) -> Int
> 
> +1 + 2  // same as numericAdd(numericUnaryPlus(1), 2)
> 
> 2.
> Operators with same "operator form" use overloading, modified to accomodate associativity and precedence.
> 
> #operator(+, name: append, fixity: infix)
> 
> func append<T>(left: [T], right: T) -> [T]
> 
> var arr = [1, 2, 3]
> 1 + 2 + 3  //=> 6
> [1, 2] + 3  //=> 1 2 3
> [1, 2] + 3 + 4  // error
> 
> Compiler must try to apply rules of both `numericAdd` and `append` in all combinations. Complexity of this should not be exponential: most branches will be cut off fast, starting from the inside.
> 
> In 1 + 2 + 3, `append` cannot be applied both to 1+2 and to 2+3, so we are left with `numericAdd`.
> In [1,2] + 3 + 4, `numericAdd` cannot be applied to [1,2] + 3, and `append` cannot be applied to 3 + 4. But if we assume `append` and `numericAdd`, then no precedence rule is defined between `numericAdd` and `append`.
> 
> Overall, algorithm for compiler is to be developed.
> 
> 3.
> Operators can define precedence (omission of parentheses), only compared to other specific operators.
> 
> #precedence(append, lessThan: numericAdd)
> 
> #precedence(numericAdd, equalTo: numericSubtract)
> 
> 4.
> Precedence applies to unary operators as well:
> 
> let v: Bool? = false
> let u = !v!  // error, precedence between logicalNot and forceUnwrap is not defined
> 
> #precedence(forceUnwrap, greaterThan: logicalNot)
> 
> let u = !v!  // true
> 
> That said, precedence of unary operators is always higher than of any binary operator.
> 
> - Anton
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list