Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exponentiation syntax sugar #172

Closed
wants to merge 6 commits into from

Conversation

Projects
None yet
9 participants
@SiegeLord
Copy link

SiegeLord commented Jul 19, 2014

Summary:

Add a new binary operator for exponentiation. This involves two additions to the
language:

  • Addition of new syntax for exponentiation (expr ** expr or expr ^^ expr)
  • Addition of a new lang item for the corresponding operator trait Pow

Rendered

### Precedence

The precedence should be above multiplication, but below casting. That is, the
following pair of assignments are equivalent:

This comment has been minimized.

@lifthrasiir

lifthrasiir Jul 19, 2014

Contributor

How about the associativity? The right-associative power operator is common, but there seems to be some cases that the power operator is left-associative so the clarification is needed.

This comment has been minimized.

@bill-myers

bill-myers Jul 19, 2014

I suggest just making it an error to have an expression where associativity makes the difference.

This simplifies the language, and it should be very rare anyway.

It's also possible to later change to left or right associativity without breaking compatibility.

This comment has been minimized.

@SiegeLord

SiegeLord Jul 19, 2014

Author

I just checked, and in every language I tried this operator is right-associative. Is it a big deal to just make that be the rule? This wouldn't be the first binary operator in Rust that is right-associative (= is, although it is not overloadable). The IndexSet operator from the Indexing RFC would also probably to be right associative.

This comment has been minimized.

@lifthrasiir

lifthrasiir Jul 19, 2014

Contributor

I do not think that the left-associative power operator is a good choice, but I do think that the choice of associativity needs a conscious decision. For the reference, the PHP RFC has a list of languages with the left-associative and right-associative power operator.

This comment has been minimized.

@glaebhoerl

glaebhoerl Jul 20, 2014

Contributor

In usual mathematical notation it's right-associative:

Without parentheses to modify the order of calculation, by convention the order is top-down, not bottom-up:

exp

I think this is a compelling argument in favor of following the same convention.

This comment has been minimized.

@SiegeLord

SiegeLord Jul 20, 2014

Author

Ok, I've specified the associativity to be to the right.

@gsingh93

This comment has been minimized.

Copy link

gsingh93 commented Jul 20, 2014

+1 to the idea in general. Having a power operator definitely isn't necessary, but it's one of those things that you just appreciate about the language.

I'd prefer **, but if that adds to much complexity to the parsing I have no problem with ^^. I definitely think we should leave the ^ operator as is.

@glaebhoerl

This comment has been minimized.

Copy link
Contributor

glaebhoerl commented Jul 20, 2014

The first case, a**b, can become a type error, requiring the user to disambiguate via parentheses: a*(*b). The second case could be handled specially by the parser (i.e. it could treat unary ** as a double-dereference). Overall, though, this token choice would not be backwards compatible.

Is there really any grammatical conflict with double-dereference, given that one is a unary prefix and the other a binary infix operator? We have some instances of the same token being used in both prefix and infix positions (-, !, *, &), and as far as I'm aware this is in itself not an issue.

The fact that a**b would have two potential meanings is more troubling, especially as it doesn't seem fantastically improbable to think that there might be circumstances where both of them would be legal, given that both multiplication and exponentiation are mathematical operations. Consider e.g. the possibility that b's type is some behavior-changing newtype of a numeric type, with dereferencing overloaded for the purpose of unwrapping the newtype.

If not for the above I would prefer **, because ^^ could also be thought of as logical XOR by the analogy of & -> &&, | -> ||, ^ -> ^^, but as it is, I think ^^ might be more prudent.

@SiegeLord

This comment has been minimized.

Copy link
Author

SiegeLord commented Jul 20, 2014

Is there really any grammatical conflict with double-dereference, given that one is a unary prefix and the other a binary infix operator?

What I'm referring to there is this currently valid code:

let a = &&1u;
let b = **a;

If ** were made a token, then it would cease to compile unless special measures were taken. Note that these special measures would not be unprecedented, as shown by this same example: && is a separate token and it gets treated specially in the unary position ( believe the same story applies to >> as well).

The fact that a**b would have two potential meanings is more troubling

The issue to me is not that it's ambiguous (I don't think it is, it'll be parsed as exponentiation in all cases), it's that it breaks existing code. There also might be a possibility where a**b gives no error at all despite being not what the user wanted (I can't come up with an example, however). I.e. the user wanted to do multiplication+dereference, but it got parsed as exponentiation and compiled.

@glaebhoerl

This comment has been minimized.

Copy link
Contributor

glaebhoerl commented Jul 20, 2014

The issue to me is not that it's ambiguous (I don't think it is, it'll be parsed as exponentiation in all cases), it's that it breaks existing code.

It's ambiguous in the sense that it could be intended to mean different things, even if the compiler resolves it by always taking it to mean one of them and not the other. It may or may not be the one the programmer intended.

There also might be a possibility where a*b gives no error at all despite being not what the user wanted (I can't come up with an example, however). I.e. the user wanted to do multiplication+dereference, but it got parsed as exponentiation *and compiled.

Yes, this is the possibility which is worrying to me. I don't think it's possible with anything in the standard library, but with e.g. third-party numeric libraries, I think it's easily within the realm of possibility. All you need is Mul and Pow impls for one particular LHS type and multiple RHS types, intentionally using newtypes on the RHS to specify different behaviors, with the newtypes allowing the use of the * dereferencing operator for unwrapping, for convenience. (This would only be possible after trait reform, but we're thinking ahead here.)

@pczarn

This comment has been minimized.

Copy link

pczarn commented Jul 20, 2014

If the user cares only about commutative multiplication and not about overloaded operators, (s)he can write *b*a.

@glaebhoerl

This comment has been minimized.

Copy link
Contributor

glaebhoerl commented Jul 20, 2014

The idea is that the potential dual meaning of a**b could conceivably enable mistakes, not that a Sufficiently Careful And Circumspect Programmer couldn't avoid making them. All else equal, it's preferable to go with the less mistake-prone option, which in this case is ^^.

@pczarn

This comment has been minimized.

Copy link

pczarn commented Jul 20, 2014

I see. It could have been forbidden from the beginning, so that a final decision on exponentiation could be made before 1.0.

@Ericson2314

This comment has been minimized.

Copy link
Contributor

Ericson2314 commented Jul 21, 2014

I absolutely agree that ^^ invites fewer careless mistakes, and I think it is a better looking token to boot.

@brson

This comment has been minimized.

Copy link
Contributor

brson commented Aug 1, 2014

The consensus of the team on this subject is that pow is not a common enough operation to warrant language support and a sigil. If we were to add a pow operator we would probably want to just go ahead and add custom ops. Closing.

@brson brson closed this Aug 1, 2014

@SiegeLord

This comment has been minimized.

Copy link
Author

SiegeLord commented Aug 1, 2014

Aww, sad. Well, I'll know who to blame for all the math libraries overloading ^/XOR for exponentiation hehe :P.

@mdinger

This comment has been minimized.

Copy link
Contributor

mdinger commented Aug 1, 2014

For what it's worth, I suggested XOR get a new >< operator (looks kinda like the X in XOR) on IRC a while back so that pow could get ^ but it got snide remarks probably because it looks like an emoticon. Makes sense to me who's never used XOR ever. If >< is practical I don't know.

Not that it matters. Oh well.

@pczarn

This comment has been minimized.

Copy link

pczarn commented Aug 1, 2014

@mdinger Bitwise operators have one character, for example & in contrast to &&.

@mdinger

This comment has been minimized.

Copy link
Contributor

mdinger commented Aug 1, 2014

@pczarn I'm aware of the comparison:

& -> &&, | -> ||, ^ -> ^^

I just thought it was nifty.

@pczarn

This comment has been minimized.

Copy link

pczarn commented Aug 1, 2014

Quite nifty, though it might be confused with the <> inequality operator used in some languages.

withoutboats pushed a commit to withoutboats/rfcs that referenced this pull request Jan 15, 2017

Merge pull request rust-lang#172 from tmiasko/stream-iter
Update futures::stream::iter docs to reflect implementation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.