You should assert!
your preconditions when:
- It's easy and cheap for the caller to check them if they want, and
- The way your type is used means there are often algorithmic invariants that mean the condition holds, and thus if you did return a
Result
almost everyone would .unwrap()
it anyway.
Now, you might also provide a non-panicking version (try_foo
or similar) as a convenience, but those are the conditions where I'd have the shorter-and-best name be the panicking one.
So what's the contrapositive? You should not panic when:
- Checking the conditions is expensive (like don't panic for bad UTF-8, either return
Result
or take a str
/String
instead so it can't happen).
- The condition is something you want to be able to change easier (like a minimum length for a password, say)
- The exact condition is complicated enough to be error-prone (though this may be indicative of an awkward API design in the first place)
- It's impossible to pre-check the condition (file existence being the usual example, or anything going over a network)
- It's unlikely that the programmer would "just know" that it's right (which, admittedly, is pretty fuzzy, and it's hard to come up with an example that doesn't violate one of the other rules)
See also Why does rust have [ ] indexing? - #3 by scottmcm
Yeah, exactly.
To look at your examples:
I'd just panic for this. It's extremely unlikely that the programmer just got arbitrary matricies from somewhere and wants the product without knowing what they are. They probably created them expecting to multiply them, so might as well let them -- they can check the sizes manually if needed.
(And of course for static sizes, const generics is coming soon to make this a compile-time check.)
I'd probably assert on this, because it's another situation where it's likely that math is making it true.
That said, this might be a place where a newtype could be interesting, so that you can communicate the guarantee in the type system without checking it. That'd let you do 1-p
or p * q
without checking, but you could have adding probabilities require re-checking (or override something to do p + q - p * q
). Dunno if it'd make sense in your case, though.
This one I'm on the edge about. I'd probably say it should either return an Option
(as other statistics like Iterator::min
and friends do) or return NAN
(as sum / count
would).