What do people feel about this? min and max are such trivial mathematical functions and I find myself including them so much, it seems a little silly that they’re not in the prelude.
Incidentally, they are currently the only items of std::cmp not in the prelude.
I would be against such a change, because the prelude should be for things that are in nearly every program. Certain kinds of programs will use it often, but others won’t. I’m not sure I’ve ever used it for anything other than the Guessing Game, for example.
Everything else is because the traits are; == is extremely common. And since it returns an Ordering, that has to be as well.
This is a fair argument, but I think they're used very frequently to write little 'mathy' bits of code, and Python for example has them available as built ins. What do you see as the harm of a larger prelude? (I'm generally in favor of expanding it; I think it should probably include Read, Write, and the io module, for example).
You're thinking of the Ord methods, min and max return the larger or lesser of the two inputs.
(But then again, I do think Ordering should be in the prelude since the methods that return Orderingare already in the prelude, and they're not very useful without the enum.)
I know, I’m saying I think these three symbols should be imported by default.
I actually tend not to use the io prelude because it requires a separate statement to import io, which I usually need for io::Result and io::Error; i.e I prefer to enumerate the traits I need to keep the use statement to one line:
use std::io::{self, Read, Write};
// vs
use std::io;
use std::io::prelude::*;
It's a symbol that's imported into every program. And to save a single use statement, there's not a whole lot of gain. Plus, the aforementioned "this is sort of a breaking change" issue.
Maybe I write my code a little differently, but I tend to use them quite a bit for non-numerical stuff, e.g.
let len = min(random_length(), max_len);
or
fn pad<W: Write>(w: &mut W, n1: usize) -> Result<()> {
let zeros = [0u8; 16];
let mut n = n1;
while n > 0 {
n -= match try!(w.write(&zeros[0..min(n, zeros.len())])) {
0 => return make_io_err(ErrorKind::WriteZero, "write failed"),
x => x
};
}
Ok(())
}
But ultimately, I feel prelude contents should be decided based on what a large number of people tend to use, not just one person like me.
On a slightly different point, it would be nice to be able to import symbols once for the whole project (i.e. a custom prelude for your whole project, or "global" project-wide imports).
It turns out its not a breaking change because prelude imports are shadowed fine. But its one use statement per module that needs them, not per crate, which adds up in my opinion.
The “receiver” of a method is the value which takes self. If swapping the position of the arguments doesn’t change the function’s semantics, I don’t think it should be a method.
The operators make the lhs the receiver because they have to in order to fit in with the way Rust’s trait system works.
However, your comment about using them on user defined Ord types doesn’t matter so much; these functions could have been defined as methods on Ord with default implementations (this would also have made them in scope by default, incidentally). I don’t think this matters so much.
FWIW what really seems odd to me is that the cmp traits are in the prelude. You almost never need them. You can use their operator forms without the traits being in scope, and most of the time people implement them by derive, rather than manually. I’m much more likely to use min or max than use these traits! Ord and PartialOrd aren’t even usable without importing Ordering. It seems almost like a mistake that they are included at all.
I’m also much more likely to need to import Read, Write, Display or Debug than these traits, in my experience, but that’s a bit out of scope.