Wrapping and Saturated wrappers arithmetic

I must ask as this is confusing and a bit annoying to be totally honest:
Why do the wrapper types Wrapping and Saturated both only implement arithmetic traits with their own types? I don't understand the issue with:

let a = Wrapping(1);
let b = a + 5;

this is confusing why it has to be like this:

let a = Wrapping(1);
let b = a + Wrapping(5);

This to me just looks very ugly and undesirable and part of me is curious why?
This feels like it reduces the ease of use the wrappers are meant to bring over using .wrapping_add and such.

In your first example do you expect b to be wrapped or not? I can see arguments for both possibilities there.

This is just a guess, but the ambiguity of what type should be returned might be a reason why + one wrapped and one unwrapped value was left unimplemented.

1 Like

Honestly I would presume it would be based on the first value but that is just me, but I can see your reasoning there considering i32 can't add u32 for example but that seems like more of a issue with potential overflow (I imagine, however that also doesn't explain why i32 can't add 16 and 8 bit types), however += for example doesn't have that excuse in my honest opinion.

Having a + b mean something different than b + a seems to me like it would be confusing unless the reader is expecting it.

It does seem pretty clear what the expected meaning of wrapped += unwrapped would be though: the same as wrapped += Wrapping(unwrapped)

2 Likes

I can see your point in first one since explicitness is a fantastic trait of rust most the time.
I suppose my overall issue is more so the fact unlike primitives where their type is typically implicitly decided by their usage, such as:

let a = 32u32;
let b = a + 99; //99 is a u32 since a is a u32

yet Wrapping and Saturated do not get this luxury which makes them very ugly to use in my honest opinion.

2 Likes

I wish integer literals like 99 would deduce not one of fixed set of primitive types, but instead any type implementing a trait IntegerLiteral which you could implement for any type. This would solve the problem.

Haskell does this. In Haskell anything implementing Integral can use regular literals.

In ibig I was trying to stick with the convention that UBig only adds to UBig etc, because that's a nice convention, but recently gave in and implemented arithmetic with primitive types, mostly because of this issue with poorly supported literals for other types.

3 Likes

I can definitely see the value in this solution; it reminds me for example in c# the ability to overload implicit conversion if required. however for this example you could simply implement addition (for example) with a equally sized primitive to get the desired result I am looking for.

I think this may also be leaving space for a potential future change to allow literals to be Wrapping<i32> instead of only i32 and such, without it being ambiguous.

Because I think there's more of a justification for x + 10 (with a literal) to work than there is for x + y where the variables have different types.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.