Lymia / enumset

A library for compact bit sets containing enums.
Apache License 2.0
91 stars 35 forks source link

Add example: initialize a variable to the empty set #41

Closed freedaun closed 1 year ago

freedaun commented 1 year ago

Please add an example of how to create an empty enumset. It may seem obvious to you, but it isn't. This is partly macro magic, and Google isn't much help either. For those that need a reminder:

#[derive(EnumSetType, Debug)]
enum Permissions {
    Read,
    Edit,
}
let permissions = EnumSet::<Permissions>::new();

The empty set is actually the most common initialization pattern.

This is one of those Rust things: if you don't already know, you'll likely not find out.

Besides, this is horrible syntax. Why not add some alternative #[derive()] which enables:

let new_set = Permissions::None;
Lymia commented 1 year ago

I'm confused in what context you're needing this. None of this sounds like anything specific to enumset rather than applying to all Rust collections in general, even the standard library Vec.

This is only a problem if you have to write exactly the following code:

let new_set = EnumSet::new(); // ERROR: you have to specify `EnumSet::<Permissions>::new()`

However, Rust supports type inference, and the following code will work with no annotations:

let mut new_set = EnumSet::new();
new_set.insert(Permissions::Read);

The second line that inserts a Read permission to new_set will allow the compiler to infer that new_set is an EnumSet<Permissions> rather than having an unknown type (and needing the ::<Permissions> part to disambiguate).

Similarly, the following would work. Since the EnumSet::new() is being used in a context where the type is known, there is no specifier needed.

fn some_func(e: EnumSet<Permissions>) {
    println!("{e:?}");
} 
some_func(EnumSet::new());

This part also works backwards, and the following will work exactly the same:

let foo = EnumSet::new();
some_func(foo);

The following context will also work for the same reason:

#[derive(Debug)]
struct MyType {
    foo: EnumSet<Permissions>,
}
println!("{:?}", MyType { foo: EnumSet::new() });

Generally, the problem Permissions::None would solve goes away in any function that uses the EnumSet to do something, except in the rare cases where type inference fails.

All of this would also work the same way with a standard library Vec or HashSet. I'm sorry you had trouble, but this is sounding like general Rust basics rather than something I can do anything specific about as a library author. EnumSet follows the same conventions as the standard library collections, to the best of my ability.

Is there something specific to enumset to mention here that I've missed? Is there a reason I should have expect that people who haven't become familiar with Rust's standard library collections will be using my library?