Rfcs: Improved .pow() syntax

Created on 27 Dec 2020  ·  16Comments  ·  Source: rust-lang/rfcs

Issue

The current .pow() syntax feels out of place for Rust; the current API forces a u32 to be used, which often facilitates the need for explicit type annotations for a number like so:

// taken from https://doc.rust-lang.org/nightly/std/primitive.u16.html#method.pow
assert_eq!(2u16.pow(5), 32);

Solution

Dedicated operator (ideal)

Ideally, I would like to see a designated operator for "power-of" operations as seen in languages like Python as it's a decently common operation. I think ** would work best for this as it's already an unofficial convention in languages, and it signifies what's happening quite well in my view. Alternatives such as ^ is already taken for use in bitwise (XOR in this case).

Generics for power-of (alternative)

Instead of the currently implemented u32 type for all operations, i'd rather see a generic implementation using impl Into<T> where T is the int used, i.e:

let x: u8 = 3;
let y: u8 = x.pow(x).pow(1u128); // essentially 3^3

Another option would be to simply use the same type for each pow, so for example with u16 if const generics are a factor:

pub const fn pow(self, exp: u16) -> u16;

Or for i64:

pub const fn pow(self, exp: i64) -> i64;
T-libs

Most helpful comment

I think ** would work best for this as it's already an unofficial convention in languages

note that x**y already means x * (*y). introducing the ** requires a breaking edition.

    let x = &5;
    let y = &6;
    assert_eq!(x ** y, 30);

All 16 comments

I don't see any benefit of the proposed changes.

First, taking power on number literals is not very often. It's more often to take power on variables bound to numbers, which are likely explicitly typed.

Then, in OP's example, I think it's actually more readable when you write the type explicitly.

Do you have an actual cases where .pow(u128) is required? That would only make sense when the left operand is a float; in that case, would .powf(f64) work?

I think ** would work best for this as it's already an unofficial convention in languages

note that x**y already means x * (*y). introducing the ** requires a breaking edition.

    let x = &5;
    let y = &6;
    assert_eq!(x ** y, 30);

Do you have an actual cases where .pow(u128) is required? That would only make sense when the left operand is a float; in that case, would .powf(f64) work?

u128 was just an example of generics, not a specific usecase.

It's alright if ** can't be implemented for me due to breaking changes as @kennytm mentioned or due to c/ocaml not having it either. I'd like to see the type change from the u32 to the same type as self if generics can't be achieved as u32 seems arbitrary. I assume if a pow operation is needed for a u8 the type that would be available is typically the same, and the factor that a value the size of u32::MAX - 1 isn't needed for a type that's max is 255.

could have used the ~ ¬ ⊻ or ⊕ for Bitwise exclusive OR and used the ^ for pow, like in Julia

https://docs.julialang.org/en/v1/manual/mathematical-operations/

That (using unicode symbols or tilde for bitwise xor) would use part of the strangeness budget for basically zero benefit.

The alternative is basically automatic coercions which are avoided elsewhere in the language and allowing them just for pow would be really strange. Yes, it's annoying to do a lot of casting, but it avoids a lot of implicit casting bugs.

IMO, the only way you're going to see an improvement for .pow() is through a dedicated maths macro, but I don't see that ever being added to the stdlib.

as it's a decently common operation

I’m not sure I follow. Is it?

Why not use ^ as pow operator and change XOR operator to .
Another idea would be to use superscript numbers and operators (⁰¹²³⁴⁵⁶⁷⁸⁹⁽⁾ⁿ⁻⁺⁼).

I would be interested to know what you think. Of course, these characters are difficult to type on the keyboard. Therefore you could include both syntaxes, but clippy could make the superscript syntax out of it.

You cannot break previous code. That's the first rule when talking about changes to Rust.

So ^ must stay as the BitXor operator.

I disagree with the fact pow is decently common operation. The only decent power operation that is common is ^2, that one is basically << 1. If we think power operations are common, then people will want to add an operator for sqrt, an operatior for exp, etc. etc.

Honestly, I’d be more interested to have custom operators than yet another fixed operator in the language.

(x << 1 is x * 2 and works for integers only. it is not x.pow(2).)

I think you might have meant 1 << x is the same as 2.pow(x) for integers.

Two major things here:

  • The need to type-annotate the method receiver is common to every method. This also happens with (2.0).sqrt(), for example.
  • The bar for a new operator is incredibly high.

Between those two things, I'm very confident that no pow-specific language features will happen here.

Bitwise XOR operator

in Rust: ^

in Julia: ⊻

possible substitutes in the ASCII table:

~

@ # $ ´ ` : ? \

possible substitutes in UTF-8:

¬

« ± × Þ

£ ¢ § ª º ¡ ¤ ¥ ¦ ¨ © ® ¯ µ ¶ · ¸ » ¿ Ø ø þ ð ÷

possible substitutes in Unicode: ⊻ ⊕

Power operator

in Rust: .pow() or .powf()

in Julia: ^

possible substitutes in the ASCII table:

^

~ ´ `

@ # $ : ? \

possible substitutes in UTF-8:

¬ » ×

ª º ¨ ¯ ® ·

£ ¢ § ¡ ¤ ¥ ¦ © « ± µ ¶ ¸ ¿ Ø ø Þ þ ð ÷

Range operator

in Rust: .. ..=

in Julia: :

possible substitutes in the ASCII table:

~ @ # $ : \

´ ` ?

possible substitutes in UTF-8:

§

¬

× ¡ ¤ ¦ Þ « »

£ ¢ ª º ¥ ¨ © ® ¯ µ ¶ ± · ¸ ¿ Ø ø þ ð ÷


https://wiki.haskell.org/Power_function

I think it's been made pretty clear already, any change to existing operators would be catastrophically breaking and will not happen and pow is not used enough to warrant another operator

I think you might have meant 1 << x is the same as 2.pow(x) for integers.

Oops yes I meant that.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

burdges picture burdges  ·  3Comments

rust-highfive picture rust-highfive  ·  4Comments

yongqli picture yongqli  ·  3Comments

rudolfschmidt picture rudolfschmidt  ·  3Comments

steveklabnik picture steveklabnik  ·  4Comments