4 ms·
Rust has the `PartialOrd` trait, which allows you to compare two things, and it returns an `Option<Ordering>`. When two things don't have an ordering, you can r
by Thiez 9y ago
Rust has the `PartialOrd` trait, which allows you to compare two things, and it returns an `Option<Ordering>`. When two things don't have an ordering, you can return `Option::None`. There is also `Ord`, which extends `PartialOrd`, and can be implemented for things that have a total ordering. Naturally, the floating point numbers (`f32` and `f64`) only implement `PartialOrd`. It's quite nice :)
- kbenson 9y agoI too was going to mention this. As a non-Rust programmer that's been following it very closely for a long time now, it's interesting to see the pain points of Rust pop up. It could just be my view and confirmation bias, but almost invariably when programmers express frustration with something harder to do in Rust, it's because they were making incorrect assumptions previously. For example, I was previously exposed to the floating point comparison problem referenced by Animats through someone complaining about comparison and sorting (IIRC) steps required in Rust to work on floats. The "Woah, you're attempting an operation on a type that doesn't hold for the invariants this operation requires, please add ornamentation to make sure it's what you mean" compile time error is something I appreciate, because I would much rather fix it initially than accidentally run into it in production at runtime and have to shoehorn a fix in later. I've had enough of that for a lifetime.
- sgift 9y ago> I too was going to mention this. As a non-Rust programmer that's been following it very closely for a long time now, it's interesting to see the pain points of Rust pop up. It could just be my view and confirmation bias, but almost invariably when programmers express frustration with something harder to do in Rust, it's because they were making incorrect assumptions previously. I'd say it's a 50:50(1) split between "the compiler is not advanced enough to understand that this is okay" and "it's okay ... really ... it's ... oh. you're right. Damn, never thought about that before" Small edit: (1)Numbers are subject to further analysis.
- andromeduck 9y agoThough sadly casting float conversions are still UB. There's a really good writeup about it here: https://github.com/rust-lang/rust/issues/10184#issuecomment-343705010 https://github.com/rust-lang/rust/issues/10184#issuecomment-...
- jfries 9y agoThis is definitely nice. But I'm thinking that NaN is a bit like null, in that it's a surprising value that may pop up which suddenly means something completely different, and code must handle it correctly. Just as some languages (like Rust) provide a way to say that a variable can't be null, I think it would make sense to have a floating point value that can't be NaN. Comparison of two non-NaNnable floating point value can then just return a boolean, because we know it will never fail.
- Animats 9y agoA key point of IEEE floating point is that NaN propagates. Any arithmetic operation that involves a NaN returns NaN. So you don't have to check until the end of the computation. Unless, of course, branching is involved. A floating point type that could never be NaN is quite reasonable for a language with exceptions. But in a language without them, what's supposed to happen?
- jfries 9y agoWell if the language is flexible enough it doesn't have to be a big annoyance to have types for both fp32 and nnfp32 (no-NaN fp32). nnfp32 guarantees things that a fp32 doesn't, for example that comparison is always legal and works as expected. This way you can perform calculations on fp32, but then have to sanitize the output before storing it back in the data structure. One way to use the type system to enforce sanitation could be if values in a database are of type nnfp32, and the only way to produce a nnfp32 is using a function which returns Option<nnfp32>, returning Some only if the value is not NaN.