Stream: general

Topic: Pattern matching on box


marmeladema (Apr 24 2020 at 19:00, on Zulip):

This is probably a regular question but what is the best way to match on an enum where one of the variant is holding a box? I have a recursive enum, so i boxed the variant value:

enum RecurEnum {
   Variant1,
   Variant2,
   Variant3(Box<RecurEnum>),
}
marmeladema (Apr 24 2020 at 19:01, on Zulip):

What i would want is writing a match pattern for Variant1 | Variant3(Variant1) => ...

marmeladema (Apr 24 2020 at 19:03, on Zulip):

but this does not work because of the box. I tried Variant1 | Variant3(inner) if *inner == Variant1 => ... but that does not work either because inner is only available in the second case

Josh Triplett (Apr 24 2020 at 19:03, on Zulip):

It's not a regular question I've seen before. :)

Josh Triplett (Apr 24 2020 at 19:04, on Zulip):

I don't think you can match "through" a box directly. And I don't think you'll be able to combine patterns like that.

Josh Triplett (Apr 24 2020 at 19:04, on Zulip):

If you only needed to match Variant3 you could do something like that.

Josh Triplett (Apr 24 2020 at 19:05, on Zulip):

Do you want to match deeper than one level?

Josh Triplett (Apr 24 2020 at 19:05, on Zulip):

As in, do you want to match a Variant3 containing a Variant3 containing a Variant2?

marmeladema (Apr 24 2020 at 19:05, on Zulip):

No i really just want Variant1 | Variant3(Variant1) => ...

Josh Triplett (Apr 24 2020 at 19:06, on Zulip):

OK, then I can think of one way you could build that reasonably ergonomically.

marmeladema (Apr 24 2020 at 19:06, on Zulip):

any other case is an error for me

Sebastian Malton (Apr 24 2020 at 19:06, on Zulip):

You could if you use box patterns (I think)

Josh Triplett (Apr 24 2020 at 19:06, on Zulip):

Sebastian Malton said:

You could if you use box patterns (I think)

That would require nightly Rust though, right?

marmeladema (Apr 24 2020 at 19:06, on Zulip):

yeah but i've read its experimental and phasing out

Sebastian Malton (Apr 24 2020 at 19:07, on Zulip):

Yeah, nightly... But I also don't know why it is being phased out

marmeladema (Apr 24 2020 at 19:07, on Zulip):

because of placement new RFC being refused or something

marmeladema (Apr 24 2020 at 19:08, on Zulip):

but maybe the box keyword will be kept _only_ for pattern matching? idk

Sebastian Malton (Apr 24 2020 at 19:08, on Zulip):

Oh, removing both let x = box Foo::new(); and if let box y = x { ... }?

Josh Triplett (Apr 24 2020 at 19:08, on Zulip):
impl RecurEnum {
    fn self_or_variant3(&self) -> &RecurEnum {
        if let Self::Variant3(ref thebox) = self {
            thebox.as_ref()
        } else {
            self
        }
    }
}
Josh Triplett (Apr 24 2020 at 19:08, on Zulip):

(Not compile-checked, rough sketch only.)

marmeladema (Apr 24 2020 at 19:09, on Zulip):

Hum I see

Josh Triplett (Apr 24 2020 at 19:09, on Zulip):

Then you could match on foo.self_or_variant3() and check for Variant1.

Josh Triplett (Apr 24 2020 at 19:09, on Zulip):

That's assuming you don't need to distinguish the two cases, but if you do you can always check that within the match.

Sebastian Malton (Apr 24 2020 at 19:11, on Zulip):

Yeah, I was correct. It does work on nightly: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=438b915dccf9f13147f7132ca670d18a

However, I think Josh is right, that there isn't really a better way...

Josh Triplett (Apr 24 2020 at 19:11, on Zulip):

Another option would be functions like .is_variant1() and .is_variant2() that check through a Variant3 too.

Josh Triplett (Apr 24 2020 at 19:11, on Zulip):

Depends on what patterns commonly occur in your code.

Josh Triplett (Apr 24 2020 at 19:12, on Zulip):

(Out of curiosity, if you don't mind sharing, what's the concrete nature of RecurEnum in your problem space? I'd love to know what the problem and variants actually are.)

marmeladema (Apr 24 2020 at 19:12, on Zulip):

Its only for one specific place in the code that's why i did not want to introduce a specific function for that at the beginning

Josh Triplett (Apr 24 2020 at 19:12, on Zulip):

Well, if it's only for the one specific place, you might just write an if let. :)

marmeladema (Apr 24 2020 at 19:12, on Zulip):

its an interpreter for a small DSL

Josh Triplett (Apr 24 2020 at 19:13, on Zulip):

Makes sense.

marmeladema (Apr 24 2020 at 19:13, on Zulip):

https://github.com/cloudflare/wirefilter/tree/cloudflare

marmeladema (Apr 24 2020 at 19:14, on Zulip):

And in my case, i have a Type enum

marmeladema (Apr 24 2020 at 19:14, on Zulip):

and Type has an Array variant ...

marmeladema (Apr 24 2020 at 19:14, on Zulip):

which holds a Box<Type> to represent the type of the values in the array

marmeladema (Apr 24 2020 at 19:15, on Zulip):

Thanks a lof the help!

Josh Triplett (Apr 24 2020 at 19:15, on Zulip):

No problem. Hope it works out. :)

rpjohnst (Apr 24 2020 at 23:00, on Zulip):

A bit late to this but if you have any plans to move your DSL nodes into an arena in the future, you would at that point be able to switch from Box to & and get normal pattern matching back.

marmeladema (Apr 25 2020 at 10:30, on Zulip):

I am not sure i understand what you mean :/

Last update: May 29 2020 at 16:05UTC