On 08.09.2016 12:08, Pyry Jahkola via swift-evolution wrote:
To stay slightly on topic of the original Subject line, I'd point out that
no one has yet demonstrated an example where the current precedence
position of `??` causes bugs at runtime.
Why do you need to see some precedence(I can create a sample project for
you on github) while this construction is so simple and obviously would be
used often and *will* cause bugs. I insist that if construction easily
allows logical bugs in it - there will be a lot of bugs in such
construction in different projects/frameworks/modules.
The original motivation by Erica simply failed to compile without the
parentheses, so it wasn't about confusion so much as about mere
Sorry, but you are just not right. The code compiles without even warning:
Swift Ver. 3.0 (Sep 6, 2016)
Platform: Linux (x86_64)
let foundIndex : Int? = 1
let lastIndex = 2
let nextIndex = foundIndex ?? lastIndex + 1
print(nextIndex) // 1
convenience. And there exist actual uses where the current precedence
brings greater convenience, e.g. when the RHS expression contains
arithmetic operations.
Like Wux, I also don't think we have any reason to adjust the precedence of
`??` from what it is.
After I showed the code compiles, would you change your opinion?
IMO the best solution which will dramatically reduce the number of future
logical errors(bugs) in code with mixed operators would be to
require(probably, just by raising a compilation warning) parenthesis when
operators from different groups are mixed in the same expression. IMO no
need in complex rules to make Swift safer. I.e. when you have a = 10 + 5 *
10 - you don't need parenthesis, when you have a = b << 4 - also all is
ok, but if you have a = b << 4 + 5 * 10 - you'll have a warning until add
parenthesis to make your intention clear. IMO this should prevent almost
all logical errors in such expressions and increase the common quality of
Swift code(in each project/framework/module).
* * *
But then, I also think we should do something to our bitwise ops:
On 08 Sep 2016, at 09:58, Xiaodi Wu via swift-evolution
<[email protected] <mailto:[email protected]>> wrote:
You and I seem to agree that `let i = 4 << 1 + 3` is rather reasonable.
Here, I would actually differ somewhat. If there's something that ought to
be higher in precedence than `+` and `*`, IMO that would be actual
exponentiation, which could be approximated in a math library by the
presently missing `**` operator, for example.
I am not sure how one can make an unintended error either reading or
writing this line of code[*].
[*] Actually, I can see precisely one way to make such an unintended
error, since I have actually done so. It has to do with Swift having
moved away from the classical C-family operator precedence table. I would
actually not be opposed to making changes that guard against such an error.
There's a fair amount of C code out in the wild that is going to be
migrated into Swift in the near future. And that code would benefit if
Swift's precedence rules didn't unexpectedly break from C – that is, not
without the programmer's awareness.
The key differences to C that I think will cause confusion in Swift are:
A) Unlike C, Swift defines `<<` and `>>` with the highest precedence.
B) Unlike C, Swift defines `&` at multiplication precedence (`*` etc.).
C) Unlike C, Swift defines both `^` and `|` at equal precedence to each
other, and that is the precedence of addition (`+` etc.).
Other than that, we also use equal precedence for all comparison operators
but at the same time remove their associativity, so that can't cause
runtime problems (as such code would fail to compile). Here's a full table,
with the notable differences marked with a red comment:
*Infix operators in C*
*In Swift 3*
// skipping unary ops etc
* / %
* << >> // (!)*
+ -
* &* / % *& // (!)*
<< >>
+ &+ - &- *| ^ // (!)*
< <= > >=
... ..<
== !=
as as? is
&
??
^
< <= > >= == != === !== ~=
|
&&
&&
||
||
(default precedence diverges here)
?:
?:
= @= // for various `@`
= @= // for various `@`
,
->
I think Jacob has a point in separating bitwise operations into their own
hierarchy. I'd recommend doing so all the way, but retaining `&` with a
higher "bitwise-multiplicative" precedence:
1) Move `|` and `^` into their own parallel precedence groups named
*BitwiseOr* and *BitwiseXor*, just above RangeFormation.
2) Move `&` into its own group *BitwiseAnd*, just above both BitwiseOr and
BitwiseXor.
3) Move *BitwiseShift* (i.e. `<<` and `>>`) just above BitwiseAnd.
That would make it so that rarely occurring*) expressions mixing `^` and
`|` would now need parenthesising, but either of them would work together
with `&`, `<<`, and `>>` just like they do in C (and just the way binary
addition relates to multiplication in the conventions of mathematics).
*) E.g. none found in https://graphics.stanford.edu/~seander/bithacks.html
<https://graphics.stanford.edu/%7Eseander/bithacks.html>.
Also integer arithmetic would stay clearly separated from bitwise
operations, which in my experience is the source of most bugs and
confusion. E.g. the expressions `a & b + c`, `a | b + c`, and `a << b - c`
all compile in both C and Swift, but are parsed in exactly opposing ways.
The whole hierarchy I'm proposing is illustrated in the attachment below,
with all changes found in the top part above RangeFormation.
— Pyry
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution