3 ms·
For an even more unpopular opinion: I find the syntactic verbosity of Rust absolutely appalling: fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::
by singularity2001 4y ago
For an even more unpopular opinion:
I find the syntactic verbosity of Rust absolutely appalling:
fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {}
Surely this monstrous code has advantages over C(++) but in no world would I voluntarily write code in this language if other options were viable. I don't get how people prefer this language outside of a very narrow application context where the lasts millisecond of optimization matters.
- thecleaner 4y agoIt's easier to read if you split it into tokens and qualifiers. The & is a reference. The '_ is a lifetime parameter. The things in the <>are types. So this is a function which doesn't mutate self and takes a mutable reference to a formatter with a sensible lifetime and returns a result which will contain either nothing (or a unit) or an error if things fail. Thank you for posting this. I had to google and read up some things.
- nextaccountic 4y agoI think most of the gratuitous verbosity comes from qualifying smt::fmt::Error. If you import it, it becomes fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), FmtError> {} But the common practice is to have an alias Result<T> to mean Result<T, whateverErrorWeAreDealingWith>. This doesn't really maps well to doing impls in the Debug trait, since this trait uses an error that is generally different from the error defined by your own application, but with some care, it can be used. Then it becomes: fn fmt(&self, _: &mut Formatter<'_>) -> Result<()> {} Okay, but what about the whole rest? it's syntactically heavy, but each part of it is very significant. Take the <'_>. It means that the Formatter struct receives a lifetime parameter but you opted to explictly omit it. In previous Rust editions, you would keep it implicit fn fmt(&self, _: &mut Formatter) -> Result<()> {} But this was confusing and ambiguous! People looked at it and sometimes didn't know there is a lifetime involved - until it showed up in compiler error messages! Now, there's two elided lifetimes in this snippet: one in the &self and one in the &mut. Rust has clear rules for this case: your snippet means fn fmt<'a, b>(&'a self, _: &'b mut Formatter<'_>) -> ... Once you learn the rules (and here are the rules https://doc.rust-lang.org/nomicon/lifetime-elision.html https://doc.rust-lang.org/nomicon/lifetime-elision.html), this makes the syntax slightly lighter. It's not an issue like the other case because if you know the rule, it's not ambiguous. The _ in place of the variable name is there just to not give a name to the formatter. It's actually a catch-all pattern (like one in the end of a match). If you wanted to give a name but disable the unused lint, you would write _formatter instead. The rest, I can't really remove much sacrificing the semantics. The only superfluous thing I love is the ->, which is much better than the C convention of putting the return type before the function name (IMO). The <> syntax itself for generic parameters sucks, and it's about the worst thing that Rust inherited from the C++ syntax. The :: also sucks, and it's also from C++ (the turbofish ::<> combines both, and it was Rust's brainchild. https://turbo.fish/ https://turbo.fish/ [0]) Actually most C++ influences on the Rust syntax is a disaster. I would much prefer to have a Haskell-inspired syntax for types, so that the type Result<A, Box<C>> would be written Result A (Box C) [0] there were multiple attempts to remove the turbofish from the syntax. this thread has a discussion of it https://news.ycombinator.com/item?id=26019053 https://news.ycombinator.com/item?id=26019053 - also see https://www.reddit.com/r/ProgrammingLanguages/comments/fe3yg9/solutions_to_the_turbofish_problem/ https://www.reddit.com/r/ProgrammingLanguages/comments/fe3yg...
- gavinray 4y agoI've found that a lot of folks writing Rust don't seem to grok lifetimes, especially the rules around elided lifetimes. I see a lot of manually-written elided lifetimes.
- zdimension 4y ago> The only superfluous thing I love is the ->, which is much better than the C convention of putting the return type before the function name (IMO). For what it's worth, C++11 supports that syntax: auto thing(int a, bool b) -> string;
- nextaccountic 4y agoIf the auto isn't the return value (supposedly string is).. then what does it means?