In the sample code here, all I wish to do is gain access to data inside an enum and panic ( or assert fail ) when the enum is not an expected variant.
My question is, can this be done with less code? I know a match could be used, but that's no less code than an if statement.
It seems like I'm having to write a lot of code to do something pretty simple. For instance I'm not happy with having to declare the "stuff" variable and then use a temporary "l_stuff" in order to initialize it. I'm just hoping there's an tighter way that this should be done. If not c'est la vie, I still love rust!
Thanks for any advice you may have to offer!
#[allow(dead_code)]
enum Foo {
Bar(u16),
Bink(u16),
}
use Foo::*;
fn main() {
let thing = Bar(1010);
let stuff: u16;
if let Bar(l_stuff) = thing {
println!("got my stuff!");
stuff = l_stuff;
}
else {
panic!("expected a bar");
}
println!("stuff={}", stuff);
}
I should add, I want to avoid the pattern below, because I do not want the panic to happen at the bottom of my code block and have my "harvested stuff variable" scoped only to the if let block. Imagine having to do 10 of these. I don't want to have 10 nested levels before I can gather up all my stuff.
#[allow(dead_code)]
enum Foo {
Bar(u16),
Bink(u16),
}
use Foo::*;
fn main() {
let thing = Bar(1010);
if let Bar(stuff) = thing {
println!("got my stuff!");
println!("stuff={}", stuff);
}
else {
panic!("expected a bar");
}
}
Thanks for the advice. You made light bulb in my head go on!
I know about those methods of course, but is there an easy way to have my Foo enum inherit unwrap? I had not thought of this, but that's exactly what I'm hoping for here. It would seem a shame to have to write that code for each enum I would want to add that to.
Is this something like what you were thinking? (I'm not sure what the difference between "custom method" and method is)
But if so, I think I can go with this as the best approach for me. Unless there's something cleaner! Each enum variant would need to have it's own method, but I guess that's pretty clean.
enum Foo {
Bar(u16),
Bink(u16),
}
impl Foo {
fn unwrap_bar(self) -> u16 {
match self {
Bar(val) => val,
_ => panic!("called `Foo::unwrap_bar()` on a not `Bar` value"),
}
}
}
use Foo::*;
fn main() {
let thing = Bar(1010);
let stuff = thing.unwrap_bar();
println!("got my stuff! stuff = {}", stuff);
let other_thing = Bink(2020);
let other_stuff = other_thing.unwrap_bar();
println!("got my other_stuff! other_stuff = {}", other_stuff);
}
That said, it would be great if I could learn how to implement my own #[derive(Unwrapper)] code attributes that could automatically do this for each variant so something like these would work...
let bar_stuff = thing.unwrap(Bar(_));
let bink_stuff = thing.unwrap(Bink(_));
// or even maybe
let complex_stuff = thing.unwrap(Complex(_,_);
( This sounds like I'm getting into macro territory. )
Yup, which is even cleaner and removes any need to implement your own custom unwrap-s. If you're running this in a function or in a loop, you can also use the same pattern to return / break early.
Awesome! I really appreciate yours and Alices's helping me think my through on this one. Made my Friday much nicer. It's funny how I can spend hours on different parts of my code, and then simple things like this require a little bit of a remake on how I think about how to write the best code.