[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 → prefix­operator­operator { [precedence-clause] }­
> postfix-operator-declaration → prefix­operator­operator { [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.


More information about the swift-evolution mailing list