3 ms·
That's significantly less readable than the C version. I still have to know what a "left-shift" and "bitwise invert" are, and if I knew that then I wouldn't hav
by NobodyNada 5y ago
That's significantly less readable than the C version. I still have to know what a "left-shift" and "bitwise invert" are, and if I knew that then I wouldn't have a problem with `<<` or `~` either. IMO `<<` is even more intuitive than `shl` because I can just look at the arrow instead of having to think about which way "left" is (and I don't even have a tendency to get "left" and "right" confused).
All the extra verbosity simply obfuscates the actual intent of the code: clear all bits in field_mask (shifted to the left by some offset). That's pretty easy to see at-a-glance from the C code (some comments could make that clearer, but this is simple enough that any experienced systems programmer will know what this does without comments).
I agree that Rust embedded code is often more readable than C, but that's done by creating abstractions to manage complexity rather than just by adding more words. For instance, one could write a wrapper struct that provides a less-tedious interface than a bitfield (like `curval.set_field(false)`).
- kennywinker 5y ago>> All the extra verbosity simply obfuscates the actual intent of the code I have a preference for verbosity in code, and I know that many people don't share my preference. That's alright - there's no exact right way to write that code. But my point was C encourages you to write code that relies on knowing secrets about specific hidden behavior in your compiler. `shl` isn't more clear than `<<`, but `wrapping_shl` and `overflowing_shl` ARE more clear, because it makes us explicitly aware of behavior that `<<` doesn't surface. As for clarity, I agree an abstraction would be best. And Rust encourages those abstractions where C discourages them. I'd still argue that the inside of that abstraction should be the verbose version, but other than the wrapping_shl that's mostly just a style/preference thing.
- NobodyNada 5y agoIn general, I'd agree with you -- I prefer spelling things out explicitly instead of using terse abbreviations. However, really common & fundamental math operations benefit from some shorthand. For instance, 'y = ax + b' is way easier to read than: let multiplied = a.wrapping_mul(x); let y = multiplied.wrapping_add(b); The "terse" equation I can instantly recognize as a linear function, while I'd have to stare at the more verbose version it for a while to figure out what it does. In my opinion, bitwise operators work the same way: if you're working in a domain where you have to write thousands of simple bitwise operations, a bit of shorthand can make the code much more expressive.
- kennywinker 5y agoThis is a good point. Programming and math are different systems. `y=ax+b` doesn’t need clarification in math because wrapping, overflowing or saturating are not concepts that apply. My pragmatic solution would be a comment pointing out the math-formula, with the code represented in the explicit+verbose way. But i can imagine language constructs that allow the simpler expression without compromising on clarity. E.g. some kind of math scope that forces you to define which operators you’re using. fn calc_linear() -> int { math(x) -> y { let * = saturating_mul let + = wrapping_add y = a*x+b } return y } There’s clearly a war between explicit and verbose going on here. Not sure the solution, but I firmly believe we can do better than C on this one.