[swift-evolution] [Discussion/Draft] Allow Precedence For Prefix And Postfix Operators
Chris Lattner
clattner at apple.com
Mon Feb 29 23:48:35 CST 2016
> On Feb 28, 2016, at 5:25 PM, Daniel Duan via swift-evolution <swift-evolution at swift.org> wrote:
>
> Hi all,
>
> I'd like to be able to specify precedence for custom pre/postfix operators.
> What's your opinion? I'll let a draft of my proposal say the rest.
I’m supportive of solving this problem, but have a few comments below:
> ## Motivation
>
> Operators compose expressions. Precedence affects the result of such
> composition. Prefix and postfix operators are not different from infix
> operator in this regard. Without the ability to specify a precedence, users
> have to rely on understanding of default precedence value and parenthesis to
> work with their costume prefix and postfix operators.
>
> For example, user might need to extend the range operator `..<` to support
> a `OpenRange` type, which represent a range with only one end specified with
> an integer:
>
> ```
> prefix operator ..< {}
> prefix func ..<(end: Int) -> HalfRange { // … }
> ```
>
> The user might want the following to mean `..< (someNumber + 3)` instead of
> `(..< someNumber) + 3`, but they need the ability to say `..<` has higher
> precedence than `+`.
>
>
> ```
> let x = ..< someNumber + 3
> ```
Keep in mind that prefix operators *must* be closely bound (without whitespace) to their operand. Your example will produce "error: unary operator cannot be separated from its operand”.
Given this, I’d strongly opposed to having:
let x = ..<someNumber + 3
parse with the unary operator less tightly bound than the binary operator it works with. Also keep in mind that unspaced binary operators cannot be juxtaposed without whitespace next to a unary operator. More specifically, this is not allowed:
let x = someNumber+..<3
you have to write it as:
let x = someNumber + ..<3
and again, I’d be pretty strongly opposed to having the unary operator bind looser than the infix operator. This example also raises the issue of what this means for a prefix unary operator the on RHS of a tighter binding binary operator.
In any case, a proposal to add precedence to unary operators should tackle these issues. If we allowed whitespace between a unary operator and its operand, that itself would introduce a different host of parsing issues that would have to be solved.
> The Swift compiler will implement the updated prefix and postfix operation
> declaration syntax as the following:
> ```
> prefix-operator-declaration → prefixoperatoroperator { [precedence-clause] }
> postfix-operator-declaration → prefixoperatoroperator { [precedence-clause] }
This style is consistent with our existing stuff, but I’ll observe that our existing “magic number” approach to precedence levels is pretty sad in general :-).
We’ve talked about (but never had time to design and implement) an approach where operators are defined as a partial order (lattice), and the compiler sorted out their relative precedence levels from this declarative spec.
-Chris
More information about the swift-evolution
mailing list