Standard operator precedence


(Xiaodi Wu) #1

Not sure if this is intentional, a bug, and/or a topic for evolution:

In Swift, bitwise operators seem to have a different precedence in
relation to other operators than they do in (all other?) C-family
languages, at least per documentation. One specific example--this
statement in C:

v = v + (v >> 4) & 0x0F0F0F0F;

is evaluated in a different order (at least, per documentation) from
this statement in Swift:

v = v &+ (v >> 4) & 0x0F0F0F0F

In C, C++, C#, Java, Python, Perl, Scala (these are the ones I've just
checked), infix + has higher precedence than infix bitwise &, but in
Swift the bitwise & operator has multiplicative precedence 150 while +
has precedence 140. Meanwhile, bitshift operators << and >> are
documented to have exponentiative precedence 160 in Swift, higher than
* / + -, which is not seen in other languages. Is this an intentional
deviation with some rationale not documented somewhere? Can we change
it back? [I know I can change it on a per-file basis, but the point
here is that, for a C-style language, having different results for
innocuous-looking statements with these operators seems to be a little
too easy a pitfall to step in.]


(Chris Lattner) #2

Yep, this is true, and this is intentional. Swift has a greatly simplified and rationalized set of precedences, and yes, that means they differ from C.

-Chris

···

On Feb 13, 2016, at 6:32 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Not sure if this is intentional, a bug, and/or a topic for evolution:

In Swift, bitwise operators seem to have a different precedence in
relation to other operators than they do in (all other?) C-family
languages, at least per documentation.


(Xiaodi Wu) #3

Very well. May I ask what the rationale might be? I'm not sure I can deduce
it from the available documentation. In other circumstances where Swift
operators differ from C (e.g. overflow handling for addition, etc.), the
behavior is amply documented and the rationale quite clear. (I should add
that Swift documentation currently introduces these bitwise operators as
'familiar' to those coming from C and Objective-C before defining what they
are, which discourages careful study.)

···

On Sat, Feb 13, 2016 at 10:10 PM Chris Lattner <clattner@apple.com> wrote:

> On Feb 13, 2016, at 6:32 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:
>
> Not sure if this is intentional, a bug, and/or a topic for evolution:
>
> In Swift, bitwise operators seem to have a different precedence in
> relation to other operators than they do in (all other?) C-family
> languages, at least per documentation.

Yep, this is true, and this is intentional. Swift has a greatly
simplified and rationalized set of precedences, and yes, that means they
differ from C.

-Chris


(Xiaodi Wu) #4

Some further study has been helpful. Am I close to the mark in answering my
own question?

- Further reading shows that Swift's rationalized operator precedence
levels broadly align with those of Erlang and Go. (However, those languages
also seem to lack documentation on how they arrived at this set of
precedence levels.)

- It is quite evident why << is considered exponentiative.

- Dennis Ritchie has explained <http://www.lysator.liu.se/c/dmr-on-or.html>
why & has lower precedence than == in C, and why in hindsight that is
better off changed. This change has been implemented in Swift/Go/Erlang and
also in other languages like Python.

- & is considered multiplicative because for two bits A and B, A & B == A *
B.

- ^ and | should have equal precedence to - and +, respectively, by
analogous reasoning.

- It also happens to be rational for & to have higher precedence than | by
analogy with && and ||.

It's a bit of a bummer, if this line of reasoning was indeed used in
arriving at these operator precedence levels, that Swift will not allow
evaluation of true * true (etc.) without casting. I would expect true &
true == true * true.

···

On Sun, Feb 14, 2016 at 1:42 AM Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Very well. May I ask what the rationale might be? I'm not sure I can
deduce it from the available documentation. In other circumstances where
Swift operators differ from C (e.g. overflow handling for addition, etc.),
the behavior is amply documented and the rationale quite clear. (I should
add that Swift documentation currently introduces these bitwise operators
as 'familiar' to those coming from C and Objective-C before defining what
they are, which discourages careful study.)
On Sat, Feb 13, 2016 at 10:10 PM Chris Lattner <clattner@apple.com> wrote:

> On Feb 13, 2016, at 6:32 AM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> Not sure if this is intentional, a bug, and/or a topic for evolution:
>
> In Swift, bitwise operators seem to have a different precedence in
> relation to other operators than they do in (all other?) C-family
> languages, at least per documentation.

Yep, this is true, and this is intentional. Swift has a greatly
simplified and rationalized set of precedences, and yes, that means they
differ from C.

-Chris


(Chris Lattner) #5

Some further study has been helpful. Am I close to the mark in answering my own question?

- Further reading shows that Swift's rationalized operator precedence levels broadly align with those of Erlang and Go. (However, those languages also seem to lack documentation on how they arrived at this set of precedence levels.)

- It is quite evident why << is considered exponentiative.

- Dennis Ritchie has explained <http://www.lysator.liu.se/c/dmr-on-or.html> why & has lower precedence than == in C, and why in hindsight that is better off changed. This change has been implemented in Swift/Go/Erlang and also in other languages like Python.

- & is considered multiplicative because for two bits A and B, A & B == A * B.

- ^ and | should have equal precedence to - and +, respectively, by analogous reasoning.

- It also happens to be rational for & to have higher precedence than | by analogy with && and ||.

Yep, this is all right.

It's a bit of a bummer, if this line of reasoning was indeed used in arriving at these operator precedence levels, that Swift will not allow evaluation of true * true (etc.) without casting. I would expect true & true == true * true.

I’m not sure what you mean here. You want multiplication defined on booleans?

-Chris

···

On Feb 14, 2016, at 10:25 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:


(Xiaodi Wu) #6

Yes, but not enough to claim limited resources needed for pressing matters.
It's not a feature anyone would clamor for, more a product of the foolish
consistency hobgoblin. Rationale: it is possible in JavaScript (for
instance) to evaluate true * true, but not in Swift. [I'm aware that
implicit casting is taking place in JavaScript, and that the return type
isn't a Boolean.] It comes into play in exactly one scenario I can think of:

Student: "Why is & a multiplicative operation?"
Teacher: "Well, because for two bits A and B, A & B == A * B."
Student: "That's interesting, let me try it with the only type I know that
represents a single bit of data."
[At this point the student should, IMO, be able to actually evaluate A * B
where A and B are booleans.]

Analogous rationale for defining &+ and &- on booleans.

···

On Mon, Feb 15, 2016 at 12:20 PM Chris Lattner <clattner@apple.com> wrote:

On Feb 14, 2016, at 10:25 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Some further study has been helpful. Am I close to the mark in answering
my own question?

- Further reading shows that Swift's rationalized operator precedence
levels broadly align with those of Erlang and Go. (However, those languages
also seem to lack documentation on how they arrived at this set of
precedence levels.)

- It is quite evident why << is considered exponentiative.

- Dennis Ritchie has explained <http://www.lysator.liu.se/c/dmr-on-or.html>
why & has lower precedence than == in C, and why in hindsight that is
better off changed. This change has been implemented in Swift/Go/Erlang and
also in other languages like Python.

- & is considered multiplicative because for two bits A and B, A & B == A
* B.

- ^ and | should have equal precedence to - and +, respectively, by
analogous reasoning.

- It also happens to be rational for & to have higher precedence than | by
analogy with && and ||.

Yep, this is all right.

It's a bit of a bummer, if this line of reasoning was indeed used in
arriving at these operator precedence levels, that Swift will not allow
evaluation of true * true (etc.) without casting. I would expect true &
true == true * true.

I’m not sure what you mean here. You want multiplication defined on
booleans?

-Chris


(Chris Lattner) #7

A feature existing in another language isn’t sufficient rationale for including it in Swift. It needs to solve a problem for Swift developers.

-Chris

···

On Feb 15, 2016, at 11:17 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Yes, but not enough to claim limited resources needed for pressing matters. It's not a feature anyone would clamor for, more a product of the foolish consistency hobgoblin. Rationale: it is possible in JavaScript (for instance) to evaluate true * true, but not in Swift.


(Jordan Rose) #8

A boolean is not a single bit of data in Swift, in the same way that "someIntegerValue & 1" cannot be used as a condition. There is a bijection between boolean values and integers with one bit set or cleared, but they are not the same type.

(You can't use '&' on a Bool either, only '&&'. That does mean Swift has no non-short-circuiting boolean AND operation, but so far we haven't needed one.)

Jordan

···

On Feb 15, 2016, at 11:17, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Yes, but not enough to claim limited resources needed for pressing matters. It's not a feature anyone would clamor for, more a product of the foolish consistency hobgoblin. Rationale: it is possible in JavaScript (for instance) to evaluate true * true, but not in Swift. [I'm aware that implicit casting is taking place in JavaScript, and that the return type isn't a Boolean.] It comes into play in exactly one scenario I can think of:

Student: "Why is & a multiplicative operation?"
Teacher: "Well, because for two bits A and B, A & B == A * B."
Student: "That's interesting, let me try it with the only type I know that represents a single bit of data."
[At this point the student should, IMO, be able to actually evaluate A * B where A and B are booleans.]

Analogous rationale for defining &+ and &- on booleans.

On Mon, Feb 15, 2016 at 12:20 PM Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Feb 14, 2016, at 10:25 AM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Some further study has been helpful. Am I close to the mark in answering my own question?

- Further reading shows that Swift's rationalized operator precedence levels broadly align with those of Erlang and Go. (However, those languages also seem to lack documentation on how they arrived at this set of precedence levels.)

- It is quite evident why << is considered exponentiative.

- Dennis Ritchie has explained <http://www.lysator.liu.se/c/dmr-on-or.html> why & has lower precedence than == in C, and why in hindsight that is better off changed. This change has been implemented in Swift/Go/Erlang and also in other languages like Python.

- & is considered multiplicative because for two bits A and B, A & B == A * B.

- ^ and | should have equal precedence to - and +, respectively, by analogous reasoning.

- It also happens to be rational for & to have higher precedence than | by analogy with && and ||.

Yep, this is all right.

It's a bit of a bummer, if this line of reasoning was indeed used in arriving at these operator precedence levels, that Swift will not allow evaluation of true * true (etc.) without casting. I would expect true & true == true * true.

I’m not sure what you mean here. You want multiplication defined on booleans?

-Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #9

A boolean is not a single bit of data in Swift, in the same way that
"someIntegerValue & 1" cannot be used as a condition. There is a
bijection between boolean values and integers with one bit set or
cleared, but they are not the same type.

(You can't use '&' on a Bool either, only '&&'. That does mean Swift
has no non-short-circuiting boolean AND operation, but so far we
haven't needed one.)

I don't know if that's strictly true, Jordan. At least once upon a
time, the performance team was fond of replacing && with & for
performance reasons (to avoid branches). I hope our optimizer has since
learned to do this for itself in all the cases that matter, though :wink:

···

on Mon Feb 15 2016, Jordan Rose <swift-evolution@swift.org> wrote:

Jordan

On Feb 15, 2016, at 11:17, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Yes, but not enough to claim limited resources needed for pressing
matters. It's not a feature anyone would clamor for, more a product
of the foolish consistency hobgoblin. Rationale: it is possible in
JavaScript (for instance) to evaluate true * true, but not in
Swift. [I'm aware that implicit casting is taking place in
JavaScript, and that the return type isn't a Boolean.] It comes into
play in exactly one scenario I can think of:

Student: "Why is & a multiplicative operation?"
Teacher: "Well, because for two bits A and B, A & B == A * B."
Student: "That's interesting, let me try it with the only type I
know that represents a single bit of data."
[At this point the student should, IMO, be able to actually evaluate A * B where A and B are booleans.]

Analogous rationale for defining &+ and &- on booleans.

On Mon, Feb 15, 2016 at 12:20 PM Chris Lattner >> <clattner@apple.com >> <mailto:clattner@apple.com>> wrote:

On Feb 14, 2016, at 10:25 AM, Xiaodi Wu >>> <xiaodi.wu@gmail.com >>> <mailto:xiaodi.wu@gmail.com>> wrote:

Some further study has been helpful. Am I close to the mark in answering my own question?

- Further reading shows that Swift's rationalized operator
precedence levels broadly align with those of Erlang and
Go. (However, those languages also seem to lack documentation on
how they arrived at this set of precedence levels.)

- It is quite evident why << is considered exponentiative.

- Dennis Ritchie has explained
<http://www.lysator.liu.se/c/dmr-on-or.html
<http://www.lysator.liu.se/c/dmr-on-or.html>> why & has lower
precedence than == in C, and why in hindsight that is better off
changed. This change has been implemented in Swift/Go/Erlang and
also in other languages like Python.

- & is considered multiplicative because for two bits A and B, A & B == A * B.

- ^ and | should have equal precedence to - and +, respectively, by analogous reasoning.

- It also happens to be rational for & to have higher precedence than | by analogy with && and ||.

Yep, this is all right.

It's a bit of a bummer, if this line of reasoning was indeed used
in arriving at these operator precedence levels, that Swift will
not allow evaluation of true * true (etc.) without casting. I would
expect true & true == true * true.

I’m not sure what you mean here. You want multiplication defined on booleans?

-Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave


(Taras Zakharko) #10

I think the teacher should just do a better job explaining group theory :wink: Its perfectly consistent to treat * and & separately, because they de-facto interpret their arguments as different types.

— T

···

On 15 Feb 2016, at 20:17, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Yes, but not enough to claim limited resources needed for pressing matters. It's not a feature anyone would clamor for, more a product of the foolish consistency hobgoblin. Rationale: it is possible in JavaScript (for instance) to evaluate true * true, but not in Swift. [I'm aware that implicit casting is taking place in JavaScript, and that the return type isn't a Boolean.] It comes into play in exactly one scenario I can think of:

Student: "Why is & a multiplicative operation?"
Teacher: "Well, because for two bits A and B, A & B == A * B."
Student: "That's interesting, let me try it with the only type I know that represents a single bit of data."
[At this point the student should, IMO, be able to actually evaluate A * B where A and B are booleans.]

Analogous rationale for defining &+ and &- on booleans.

On Mon, Feb 15, 2016 at 12:20 PM Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Feb 14, 2016, at 10:25 AM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Some further study has been helpful. Am I close to the mark in answering my own question?

- Further reading shows that Swift's rationalized operator precedence levels broadly align with those of Erlang and Go. (However, those languages also seem to lack documentation on how they arrived at this set of precedence levels.)

- It is quite evident why << is considered exponentiative.

- Dennis Ritchie has explained <http://www.lysator.liu.se/c/dmr-on-or.html> why & has lower precedence than == in C, and why in hindsight that is better off changed. This change has been implemented in Swift/Go/Erlang and also in other languages like Python.

- & is considered multiplicative because for two bits A and B, A & B == A * B.

- ^ and | should have equal precedence to - and +, respectively, by analogous reasoning.

- It also happens to be rational for & to have higher precedence than | by analogy with && and ||.

Yep, this is all right.

It's a bit of a bummer, if this line of reasoning was indeed used in arriving at these operator precedence levels, that Swift will not allow evaluation of true * true (etc.) without casting. I would expect true & true == true * true.

I’m not sure what you mean here. You want multiplication defined on booleans?

-Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #11

Yes all good points--and very interesting history from Dave. Thanks all.

···

On Mon, Feb 15, 2016 at 1:47 PM Taras Zakharko <taras.zakharko@uzh.ch> wrote:

I think the teacher should just do a better job explaining group theory :wink:
Its perfectly consistent to treat * and & separately, because they de-facto
interpret their arguments as different types.

— T

On 15 Feb 2016, at 20:17, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

Yes, but not enough to claim limited resources needed for pressing
matters. It's not a feature anyone would clamor for, more a product of the
foolish consistency hobgoblin. Rationale: it is possible in JavaScript (for
instance) to evaluate true * true, but not in Swift. [I'm aware that
implicit casting is taking place in JavaScript, and that the return type
isn't a Boolean.] It comes into play in exactly one scenario I can think of:

Student: "Why is & a multiplicative operation?"
Teacher: "Well, because for two bits A and B, A & B == A * B."
Student: "That's interesting, let me try it with the only type I know that
represents a single bit of data."
[At this point the student should, IMO, be able to actually evaluate A * B
where A and B are booleans.]

Analogous rationale for defining &+ and &- on booleans.

On Mon, Feb 15, 2016 at 12:20 PM Chris Lattner <clattner@apple.com> wrote:

On Feb 14, 2016, at 10:25 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Some further study has been helpful. Am I close to the mark in answering
my own question?

- Further reading shows that Swift's rationalized operator precedence
levels broadly align with those of Erlang and Go. (However, those languages
also seem to lack documentation on how they arrived at this set of
precedence levels.)

- It is quite evident why << is considered exponentiative.

- Dennis Ritchie has explained <
http://www.lysator.liu.se/c/dmr-on-or.html> why & has lower precedence
than == in C, and why in hindsight that is better off changed. This change
has been implemented in Swift/Go/Erlang and also in other languages like
Python.

- & is considered multiplicative because for two bits A and B, A & B == A
* B.

- ^ and | should have equal precedence to - and +, respectively, by
analogous reasoning.

- It also happens to be rational for & to have higher precedence than |
by analogy with && and ||.

Yep, this is all right.

It's a bit of a bummer, if this line of reasoning was indeed used in
arriving at these operator precedence levels, that Swift will not allow
evaluation of true * true (etc.) without casting. I would expect true &
true == true * true.

I’m not sure what you mean here. You want multiplication defined on
booleans?

-Chris

_______________________________________________

swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution