I would say Yes and No. I think Effective C++ was one of the first books to use this name, but now there is a publisher who uses "Effective xxxxx" in a series: https://www.amazon.com/dp/B08R2PKL9M?binding=paperback&searc... but that publisher does not seem related to the original Effective C++ author...
As a Rust semi-noob I do get that Rust does things differently from many other languages, and can appreciate why. But it's one thing being told "You can't do this common thing in Rust", and another thing understanding what are the idiomatic alternatives that do actually work. These often seem to relate to overall program design (e.g. numbers of readers and writers of a data structure) rather than using a single alternative language construct.
YMMV but I found that 'Effective Rust' came closest to the 'what should I do instead' guidance I was looking for, in terms of getting me past some of the blockers I'd encountered. It also helped me begin to read between the lines in the Rust book and the O'Reilly book, where some quite important consequences are sometimes not explicitly spelt out.
When I programmed in C a lot, I had methods of working so that by the time the code compiled, there was a good chance it worked. That, very nice, feature is a property of how you program as much as the language. I have the same method and same feeling with Go, always subject to stupid bugs like “reverse the sense of the logic test on the innermost loop” or that sort of thing.
There is a class of bugs that I call “surprising results of innocuous seeming simple rules” which I can’t imagine anything will prevent except maybe a ruthless dedication to simplicity, which is hard for people who enjoy creating new code and implementing new ideas.
> The boilerplate can be significantly reduced by implementing and using the Default trait, as described in Item 5:
Yes, standard and good advice.
> That's a more general concern: the automatically derived implementation of Default only works if all of the field types implement the Default trait. If there's a field that doesn't play along, the derive step doesn't work:
> The code can't implement Default for chrono::Utc because of the orphan rule, so this means that
... you have to implement Default for your struct manually.
> all of the fields have to be filled out manually:
What?
> These ergonomics can be improved if you implement the builder pattern for complex data structures.
No!
Does this document contain actually good advice, or is this just some guy's thoughts?
Two things I have the most problems with in Rust, as a noob:
- I have a hard time figuring out which features I need to add from a crate and which ones exist in a crate.
- I have a hard time figuring out if something doesn't work because a trait is missing and it's not just unclear that it is missing but also where it can be found.
> - I have a hard time figuring out which features I need to add from a crate and which ones exist in a crate.
The documentation for the crate should make clear that a feature should be enabled for their APIs, the list of all features would always be in the Cargo.toml. Recent rustc will tell you when you call method that is configured out, and which feature you need to enable.
> - I have a hard time figuring out if something doesn't work because a trait is missing and it's not just unclear that it is missing but also where it can be found.
If the compiler doesn't clearly tell you that a trait is missing, please file a ticket with a repro case. A trick for finding where any item is defined, if you know the name already, is to use the name in some way. The compiler will then fail to find it in scope and do a global search. If it finds it then, it will tell you the appropriate import path.
10 comments
[ 4.1 ms ] story [ 13.8 ms ] threadThe word Effective is trademarked in the context of computer reference books: https://tsdr.uspto.gov/#caseNumber=75936440
Anyway the introduction to Effective Rust explains the choice of name in a way: https://effective-rust.com/intro.html
YMMV but I found that 'Effective Rust' came closest to the 'what should I do instead' guidance I was looking for, in terms of getting me past some of the blockers I'd encountered. It also helped me begin to read between the lines in the Rust book and the O'Reilly book, where some quite important consequences are sometimes not explicitly spelt out.
There is a class of bugs that I call “surprising results of innocuous seeming simple rules” which I can’t imagine anything will prevent except maybe a ruthless dedication to simplicity, which is hard for people who enjoy creating new code and implementing new ideas.
Hmm.
> The boilerplate can be significantly reduced by implementing and using the Default trait, as described in Item 5:
Yes, standard and good advice.
> That's a more general concern: the automatically derived implementation of Default only works if all of the field types implement the Default trait. If there's a field that doesn't play along, the derive step doesn't work:
> The code can't implement Default for chrono::Utc because of the orphan rule, so this means that
... you have to implement Default for your struct manually.
> all of the fields have to be filled out manually:
What?
> These ergonomics can be improved if you implement the builder pattern for complex data structures.
No!
Does this document contain actually good advice, or is this just some guy's thoughts?
- I have a hard time figuring out which features I need to add from a crate and which ones exist in a crate.
- I have a hard time figuring out if something doesn't work because a trait is missing and it's not just unclear that it is missing but also where it can be found.
The documentation for the crate should make clear that a feature should be enabled for their APIs, the list of all features would always be in the Cargo.toml. Recent rustc will tell you when you call method that is configured out, and which feature you need to enable.
> - I have a hard time figuring out if something doesn't work because a trait is missing and it's not just unclear that it is missing but also where it can be found.
If the compiler doesn't clearly tell you that a trait is missing, please file a ticket with a repro case. A trick for finding where any item is defined, if you know the name already, is to use the name in some way. The compiler will then fail to find it in scope and do a global search. If it finds it then, it will tell you the appropriate import path.