Raunak Bhagat
09/06/2024, 9:07 PMenum MyEnum {
Variant1,
Variant2,
}
use MyEnum::*;
match my_enum {
Variant1 => ...,
Variant2 => ...,
}
The problem here is with the use MyEnum::*;. Although it is more concise, this can lead to a whole suite of nasty issues further down the line.
The specific problem is that Variant1 and Variant2 will work here. But imagine if we change the definition of MyEnum to be:
enum MyEnum {
Variant1,
NewVariant2,
}
If we make the above change, the following code will still continue to compile successfully:
use MyEnum::*;
match my_enum {
Variant1 => ...,
Variant2 => ...,
}
The reason being is that the left hand side of the match-arrow is a pattern-matching construct. Pattern matches can either be the name of one of the enum's variants OR, if the enum does not have that name, it can be treated as an identifier.
Therefore, after our change to the definition of MyEnum, Variant2 => ... will instead be treated as a variable binding! More specifically, Variant2 will now bind to MyEnum::NewVariant2.
This can become even more ugly when we further modify our definition of MyEnum. For example, consider this new definition:
enum MyEnum {
Variant1,
NewVariant2,
MyNewSuperCoolVariant3,
}
and consider our still unmodified original match condition:
use MyEnum::*;
match my_enum {
Variant1 => ...,
Variant2 => ...,
}
Here, Variant2 will be treated as a variable binding and will bind to MyEnum::NewVariant2 and MyEnum::MyNewSuperCoolVariant3 !!! This can lead to a whole host of ugly problems down the road and creates a whole bunch of technical debt.
The only sign that rustc will give to you when compiling that program is a casing-warning. Specifically, it'll say something like "You are using CamelCase for this variable (Variant2), but instead you should be using snake_case (variant_2)". This is just a warning! We've made breaking changes to our definition of MyEnum, and the only sign that we get from rustc is a silly little case-warning!
This defeats the entire purpose of using a good algebraic type system that Rust gives us.
Please resort to using the full, qualified variant names of enums! Something like:
match my_enum {
MyEnum::Variant1 => ...,
MyEnum::NewVariant2 => ...,
MyEnum::MyNewSuperCoolVariant3 => ...,
}
I know it's more verbose, but it will save us a LOT of headaches down the line in the future! Thanks in advance!Raunak Bhagat
09/06/2024, 9:12 PMDesmond Cheong
09/06/2024, 9:18 PMBringing the function’s parent module into scope with use means we have to specify the parent module when calling the function. Specifying the parent module when calling the function makes it clear that the function isn’t locally defined while still minimizing repetition of the full path. The code in Listing 7-13 is unclear as to where add_to_waitlist is defined.
On the other hand, when bringing in structs, enums, and other items with use, it’s idiomatic to specify the full path.
Raunak Bhagat
09/06/2024, 9:21 PMRaunak Bhagat
09/06/2024, 9:25 PMbuck2 build tool (written in Rust and developed at Meta) actually has a really cool styling guideline for new contributors. Things such as what Desmond and I mentioned in this thread. Daft could also have something similar!Raunak Bhagat
09/06/2024, 9:26 PM