4 ms·
>I can easily write something that doesn't use traits or iterators Do you mean that you aren't using them at all or you aren't defining your own? Because I wou
by sebzim4500 4y ago
>I can easily write something that doesn't use traits or iterators
Do you mean that you aren't using them at all or you aren't defining your own? Because I would expect any nontrivial rust program (outside of some obscure embedded context maybe) to make use of the traits that are in the standard library/your dependencies. Similarly, you can't even write a for loop without using iterators.
>panics all the time
That might be fine, depending on your usecase. Presumably if you were going to put it into production you would go through and handle the errors. Crucially, by grepping for `unwrap` and `expect` you can find the panics very easily.
>calls clone all over the place to satiate the BC
If it's not a performance issue then this might be fine.
>I could create very unidiomatic code that was still correct, but not performant or easy to read/use
This is true in every language. The value proposition of rust is that if you do write idiomatic code then it will likely be reasonably performant and easy to maintain.
>But with all those features surely I'm missing as many pitfalls as I know about?
Maybe, but not every program will need to use every feature. Quite a few of the more advanced features are mainly useful for libraries, for example.
- couchand 4y ago> Crucially, by grepping for `unwrap` and `expect` you can find the panics very easily. I write Rust code up and down the stack, and this is the thing that ticks me off more than anything else. You can get most of them looking for this stuff (and a handful of others), but there are just so many places in vanilla Rust that exhibit the Wrong Behavior By Default, e.g. a[i] = x + 1; Which looks so innocent but can panic in two places! Ugh.
- throwaway894345 4y agoOne can conceive of tooling that can find these panics for you so you don't need to grep, but I'm not aware of anything that's been written at this time.
- pitaj 4y agoThere are two clippy lints that cover these possible panics: - indexing_slicing - integer_arithmetic Enabling those will throw an error on usage in your codebase. Also it's worth noting that arithmetic is only checked against overflow when building in debug mode by default.
- couchand 4y ago> Also it's worth noting that arithmetic is only checked against overflow when building in debug mode by default. Yes, the default behavior in release mode is even worse!
- sophacles 4y agoSure, you wrote 2 overflows - a buffer one and an integer one. Would you rather it silently breaks?
- couchand 4y agoNo, I'd rather it not compile!
- tialaramex 4y agoIf x's Add doesn't have panic on overflow then you get rid of the panic risk on the right hand side. For example if x is Wrapping<u8> then it can't panic. Having chosen Wrapping<u8> you will presumably not be startled when 255 + 1 == 0 Or if x is Saturating<i16> again, no panic, but 32767 + 1 == 32767 Wrapping and Saturating really exist (well Saturating isn't stable, but it's in nightly) and if you're in a space where that's what you want, you can express it cleanly in Rust. Most programmers just mean the integers they learned in school which don't have a "maximum" or "minimum" they go on forever, and so overflow means the programmer's model of the world mapping those integers to a type like usize was wrong and this code is faulty. [Edited to add: This doesn't quite work because in the end neither Wrapping nor Saturating implement Add over the normal integers, since it's not certain what you intend if you wrote that, better to have an error asking you to explain. AddAssign works though] Now, there aren't any built in types whose IndexMut can't panic AFAIK, but we could build one, and if a was such a type then a[i] doesn't panic either. For example we can imagine a is a (hypothetical) PythonDict while x is a Saturating<i16> and now our code just compiles to add 1 to x, saturating if necessary, and then shove the result in our PythonDict under the value of i.
- couchand 4y agoYes, Wrapping and Saturating very neatly provide behavior you might want in some context. I use them a lot in embedded contexts. Since indexing is nearly always fallible, it should be fallible!
- tialaramex 4y agoRust's slices (the most obvious thing you would index) have three ways to index them, if you are out of bounds the consequences are Undefined Behaviour; panic; and return None. Today those are provided by get_unchecked(), the Index operator and get() respectively. [[ Calling get_unchecked() is unsafe of course, but it's potentially faster because it has no bounds check ]] I'm confident we sometimes want each of the three options, so if we're having the Index operator return None then get() presumably panics, or at least some new function is provided with that behaviour. I reckon this just drives annoyance that [k] has to be unwrapped, while get(k) does what people actually wanted [k] to do. I could be wrong, but that's my sense.