Why doesn't rust allow float/int division by default? [closed] - rust

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 months ago.
Improve this question
The following snippet:
let a: f32 = 2.0;
let b: i32 = 12;
println!("{}",a/b);
fails to compile, with the error message indicating that there is "no implementation for 'f32 / i32'. Now, I understand what this error means, and that I could easily fix it by casting b before dividing. More to the point, the compiler also tells me that I could fix this without modifying the snippet above by implementing the trait Div<i32> for f32.
I don't actually need to divide ints by floats in this manner, but the compiler's message I got made me curious enough to ask the following question: why isn't Div<i32> already implemented for f32?
Of course it would be pretty easy for anyone to implement this by themselves, but I assume it must mean something that it's not a default feature. Is there some complication with the implementation I'm not thinking of? Or is it that the possibility of f32/i32 division somehow lead to "language gotcha's"? Or maybe it's just that rust is more "barebones" in this regard than I assumed?

There are multiple reasons. For one, it's not clear what the return values should be. Should 12 / 2.0 return a float or an integer? What about 12.0 / 2? Many languages opt to just return floats, but this results in hidden conversion costs. Rust as a language tries to be very explicit, especially in case of non-zero cost abstractions.
There is also type safety to consider. Sometimes doing arithmetic between ints and floats indicates a logic error.

Related

Rust ownership, how to return a ref for a struct? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last month.
Improve this question
I generate an instance A from instance B's method and managed by B, but I want return A. How to implement this?
For this codes (playground link) I want generate a history for the RedPacket, managed by RedPacket (push into the Vec) and return history ref to print, but the compiler throw out: cannot move out of history because it is borrowed
How implement this? Or is this a right way in rust world?
It isn’t right way in only “Rust world”, it’s completely wrong in whole programming world. 1. Local variables are stored on the stack, so after function call they are deleted. 2. You’re trying to move your local variable after borrowing it. You are trying to return reference to invalid buffer, and compiler prevents it.
You can return a reference to the last Vec member though:
self.histories.push(history);
self.histories.last()

Is it possible to implement From<T> for T in Rust? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 months ago.
Improve this question
I have an enum, Angle, which has two variants, Degrees and Radians. I wanted to implement From for these, but it doesn't let me:
enum Angle {
Degrees(f64),
Radians(f64)
}
impl From<Angle> for Angle {
fn from(value: Angle) -> Self {
match value {
Angle::Degrees(deg) => Angle::Radians(deg / 180.0 * PI),
Angle::Radians(rad) => Angle::Degrees(rad / PI * 180.0)
}
}
}
which throws
error[E0119]: conflicting implementations of trait `std::convert::From<Angle>` for type `Angle`
--> src\lib.rs:45:1
|
45 | impl From<Angle> for Angle {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> From<T> for T;
Some errors have detailed explanations: E0119, E0412, E0425.
For more information about an error, try `rustc --explain E0119`.
From what I can see there are three options for this:
I clarify this to the compiler in some way
I add two separate functions to_degrees and to_radians
I separate Angle::Degrees and Angle::Radians into two separate structs
If 1 is not possible, which is preferred of 2 and 3?
I wanted to implement From for these
By that code, it appears that you want From::from to turn a value in degrees to a value in radians and vice versa. However, this is not only:
impossible, because any From<T> is already implemented by the core library for T;
but also unintuitive, because this is far from what a From conversion should be doing.
As such, trying to get the compiler to accept this is out of the question. The two alternatives provided are actually good, and are not mutually exclusive.
Whether to define independent structs for angles in degrees and angles in radians is case dependent. For what it's worth, the Rust API guidelines show how the newtype pattern can be used to prevent serious bugs by preventing you from mixing different measures. On the other hand, this type already does that.
#1 is indeed not possible. Rust has a blanket implementation impl<T> From<T> for T and you cannot overwrite it. Besides semantically what you are trying to do is not a From conversion, but rather changing a representation of some type.
I would strongly recommend #2. It is very idiomatic and anyone can tell after a glance what this methods would do (in contrast to what you written in your example).
You could do #3 but it's up to you how you want to design your code. If you already started with an enum it's probably the better fit for your problem, so I would recommend sticking to it. But if you decide that having two different structs is better for you, then #3 is still fine.

Is it appropriate to mark functions unsafe if the user's inputs can break invariants? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
Improve this question
It's common in Rust to enforce invariants about the state of types by exposing a limited API. However, invariants can be easily broken if the invariant is difficult or prohibitively computationally expense to check and return an error.
For example, imagine we have a function that takes an integer and, for whatever reason, fails if that integer is a prime number. It may be too expensive to check that the input is not prime. Is it appropriate to mark such a function unsafe as a way of saying, "This method could potentially operate in an unexpected way if the input is prime, but we trust you and don't waste effort checking"?
If such an input could cause obvious undefined behavior (UB), then I imagine the answer is yes. But if it's not immediately clear if it could UB, I am uncertain whether such an API should be complicated with an unsafe attribute.
If a broken invariant could cause Undefined Behaviour then the convention would usually be to check the invariant in the "obvious" usage of the API, but also provide a less convenient unsafe variant where the user can take responsibility for the checks themselves.
The unsafe variants of functions usually have _unchecked as a suffix. For example:
/// Will panic if `p` is prime
pub fn do_stuff(p: u64) {
assert!(!is_prime(p), "The argument must not be prime");
unsafe { do_stuff(p) }
}
/// # Safety
/// It is Undefined Behaviour if `p` is prime
pub unsafe fn do_stuff_unchecked(p: u64) {
todo!()
}
In a lot of cases it's more appropriate to return a Result rather than panicking. I used panicking in the example to reinforce that unsafe is about memory safety only.
See Also
Lots more examples in Rust std

Why is wrapping a match statement in an Ok considered bad form? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
In a blog post, Rust contributor withoutboats mentions:
Most of my functions with many return paths terminate with a match statement. Technically, these could be reduced to a single return path by just wrapping the whole match in an Ok, but I don’t know anyone who considers that good form, and I certainly don’t.
A (somewhat contrived) example of this--
bad:
Ok(match response {
UserResponse(user) => user,
ItemResponse(item) => item?,
})
better:
match response {
UserResponse(user) => Ok(user),
ItemResponse(item) => Ok(item?),
}
Why is that the case?
This is kind of a tricky question to answer. I personally can't recall ever seeing anyone express this opinion before. To be fair, I can't say that I've ever heard the opposite. That is, I don't remember anyone ever explicitly encouraging this sort of pattern in code.
I've certainly used this pattern before, although somewhat sparingly. To demonstrate, this typically occurs when you have a match expression with several cases in a tail expression that returns a Result, and you don't want to write Ok for each case. Like this:
Ok(match something {
Something::Foo => 1,
Something::Bar => 2,
Something::Quux => fallible?,
Something::Baz => return Err(...),
})
As opposed to
match something {
Something::Foo => Ok(1),
Something::Bar => Ok(2),
Something::Quux => fallible,
Something::Baz => Err(...),
}
It's not a huge difference, but if you have a lot of Ok cases, it can get a bit annoying. Or at least, this was the primary complaint in Boat's blog post (in defense of Ok-wrapping).
Another variant of this pattern is 1) when your function returns a Result, 2) the tail expression of the function is also a Result, 3) the error types are not the same and 4) the error type in (1) has a From impl for the error type in (2). That is, instead of writing
something.fallible().map_err(From::from)
one can write
Ok(something.fallible()?)
? is so ubiquitous that I've always kind of chalked up the difference between these to personal style.
I can't possibly know what the blog author had in mind when saying that this was poor form. My guess---and I somewhat share this---is that there is a lack of symmetry between the arms of the match expression. Some of them are effectively early returns while others aren't early returns at all. I could see how some might consider that jarring.
Otherwise, I do occasionally use both of these patterns, but not religiously so. If it comes up and it makes sense, then I don't have too much of a problem with it.

What's the practical use of Option in rust? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Consider this example
fn main() {
let mut i: Option<i32> = None;
//after some processing it got some value of 55
i = Some(55);
println!("value is {:?}", i.unwrap());
}
In go, nil represents the zero-value of that type.
However in rust, it represents absence of a value. How is absence of a value useful in practice?
When a variable with a type is declared, it must have some value either initialized or un-initialized. Why will one declare it to have it absent?
Also please explain, at what point the memory is allocated for i during the initial declaration or when i gets some value?
I might be asking a stupid question, but want to get my head around the need of this concept.
How is absence of a value useful in practice?
A simple example is a function that looks for the first matching element in a collection. It may find it, and return it, or not find any.
The docs give a few more cases:
Initial values
Return values for functions that are not defined over their entire input range (partial functions)
Return value for otherwise reporting simple errors, where None is returned on error
Optional struct fields
Struct fields that can be loaned or "taken"
Optional function arguments
Nullable pointers
Swapping things out of difficult situations
Now, you may ask: why don't we use one of the values to mark an empty one? For two reasons:
There are cases where you do not have a valid "zero-value" or a valid "invalid" value. In this case, you have to use some flag somewhere else to store the fact that something is invalid.
In general, it is simpler to use the same solution everywhere than having to mark and document which is the "none" value.
Why will one declare it to have it absent?
This is different than initialized/uninitialized values. Option is simply a type that contains either "nothing" (None) or a "value" of some type (Some(value))
You can conceptually see it as a struct with a flag and some space for the value itself.
Also please explain, at what point the memory is allocated for i during the initial declaration or when i gets some value?
That depends on the implementation. One could decide to implement Option using a pointer to the value, which means it could delay allocating.
However, the most likely implementation is avoiding pointers and keeping the value plus an extra flag. Note that, for some types, you can also optimize further and avoid the flag altogether. For instance, if you have an Option of a pointer, you can simply use the zero value for None. In fact, Rust does such a thing for types like Option<Box<T>>.

Resources