5 ms·
I too am having problems 'getting into' Rust because of all that salad-y syntax. It looks like Perl at some times ;__;
by fb03 7y ago
I too am having problems 'getting into' Rust because of all that salad-y syntax. It looks like Perl at some times ;__;
- eterps 7y agoMy thoughts exactly, it reminds me a lot of Perls (lack of) readability. I would love a Rust variant with a mix of Python/Nim/F#/OCaml syntax.
- johnisgood 7y agolet dest: Vec<String> = dest.split(',').map(|name| name.trim().to_string()).collect(); impl< $($kind: TryFrom< Value >,)* F > allMut< ($($kind,)*) > + 'static, F::Output:
- steveklabnik 7y agoThe first line is formatted by rustfmt to be let dest: Vec<String> = dest .split(',') .map(|name| name.trim().to_string()) .collect(); which makes it quite a bit more clear what's going on, IMHO. Cramming stuff into one line makes things unreadable no matter what the language. That second line, while intense, is the syntax for writing macros, not normal Rust code. As always, it depends on what you're doing, but you almost never need to write macros yourself.
- johnisgood 7y agoYes, the formatted version seems better. My complaint with Rust is the heavy use of symbols. I do not know what is going on most of the time because of it. How would you format this example? fn deserialize< D: de::Deserializer< 'de > >( deserializer: D ) -> Result< Self, D::Error > { In my opinion it is not obvious what most of the code is doing when you have hundreds of lines of code and each line contains lots of symbols. Again, this is just my opinion and perhaps my limitation. I looked at many codebases and found that they were not easy on chaining and using symbols. I do not deny that they could have written it in a more readable way, but generally it was not the case in my experience, based on these projects at least.
- steveklabnik 7y agoI think it really depends on what you're used to. You could format this alternately as: fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de>, { using the `where` clause makes it easier to see the bits, in my opinion. That said, even with your version, you can read it almost front to back: "A function named deserialize that takes one type parameter, D, that implements the Deserializer trait. It takes one argument of type D, and returns a Result of either Self or D's error type." The symbols in this example: * <> are used for generics, which is common in other languages. * : is for two things: trait bounds; that is, restricting a type parameter by a given trait. I'm not sure where this came from, but it feels fairly intuitive after a bit, at least to me. Second, for indicating the type of arguments. Both are about defining the types of things, so even though they're different, they feel consistent, at least to me. * ' is used for lifetimes; this comes from OCaml, which many programmers aren't familiar with. Nobody likes this syntax, but nobody could come up with a better syntax. * () is used for the parameter list to a function, this is extremely common in languages. * -> indicates the return type * :: is for navigating namespaces; the first instance is for a module, the latter is for an associated type. Similar to :, these are different but similar things, so the similar syntax makes it easier to me. It's all just practice. Being familiar with a wide variety of languages helps, because Rust draws from a lot of other places.
- johnisgood 7y agoThank you for the brief explanation (or the meaning) of the symbols! Is there a place where it is laid out in a similar fashion? It would help tremendously.
- steveklabnik 7y agoAny time! https://doc.rust-lang.org/stable/book/appendix-02-operators.html https://doc.rust-lang.org/stable/book/appendix-02-operators.... (I also just realized HN formatting messed up my re-formatting, I've fixed it now)