Range Operators and Negative Numbers

My apologies if this has been asked before (I didn't find it in search), but what are the reasons for needing to put parenthesis around the trailing value of a range operator if it is negative (unary minus operator). Example:
-1000..<(-900)
Is this a bit of ugliness in the parser that can be corrected, an unavoidable syntax conflict or a surprising operator precedence issue?

Fortunately the fix, when applied, solves it by adding whitespace to both leading and training operands. However, it would be great to be consistent in the need for whitespace with the range operators for all operands.

Without whitespace, -1000..<-900 parses to a call to a func ..<- (_: Int, _: Int) but, as the ..<- operator does not exist, as part of compilation failure messages the compiler sees that you may have meant -1000..<(-900) and provides an appropriate suggestion.

1 Like

One could, if they wish, create operators ...- and ..<- to do exactly that.

I have not personally done so, but I have made a prefix operator -āˆš

3 Likes

Swift allows you to define arbitrary operators of your own of any length. A side effect is that you cannot juxtapose operators, because the parser would be unable to deduce where one operator ends and the next begins (at least without severe performance hit compounded by type inference). To keep things simple, a contiguous string of operator characters is always considered to be a single operator.

// A human can reason about the probable intended semantics of this,
// but the compiler cannot:
let x = ------y
// Hence ā€œError: Cannot find operator '------' in scopeā€

// But you can communicate your intent to the compiler
// by breaking the operators up with parentheses:
let x = -(-(-(-(-(-y)))))

// Or if this was what you meant instead:
let x = --(--(--y))

// Or this:
let x = -(--(-(--y)))

// Or any other permutation...

As @Nevin says, if you find yourself using a certain combination often, you can define the entire sequence as a single operator in order to codify the intent, and then you do no longer need parentheses each time.

Thank you for the kind and thoughtful responses. I can see how there would be ambiguity if a ..<- operator was defined and existed in that scope, but absent that, can't the parser consume the characters one at a time until it hits the - and goes that isn't part of an operator I know about and so it must be the start of a new token? There seems to be plenty of info available in the context (of a likely range operator) to say I'm expecting an integer value next and a unary minus - is consistent with that.

It still seems like a weakness of the parser or lexical analyzer that it doesn't recognize a negative integer operand following a range operator. If nothing else, they could special case it.

That is the problem. An operator could be in any imported dependency. In the case of documentation examples it may only be hypothetical anyway. With the simple rule that an operator token greedily absorbs every character until it encounters something illegal, tools like formatters, syntax highlighters and such can do their job without needing access to a compiler or any dependencies. To make tokenization dependent on information gleaned from fully compiled context would throw a wrench into all that.

I personally am unconvinced by style guides that recommend unspaced ranges. When all infix operators are uniformly spaced anyway, developers are far less likely to encounter this in the first place.

is it in the swift language document or where? i am always (subconsciously) putting white spaces around ... and ..< but would be glad to change if swift recommends doing so.

Swift itself hasnā€™t decided on an official style guide for that sort of thing (yet). There are only the API Design Guidelines which deal with naming, but not formatting.

Individual companies often enforce a set of rules for consistency among their own developers. I have seen some that require no spaces beside range operators. And I have seen others that require one space on each side. That is all I was referring to. My own opinion is squarely in the spacing camp and one of the reasons is the issue discussed in this thread.