Common code for match patterns

How can I avoid having nested matches when I have some common code shared by some patterns?

This is a contrived example:

enum Example {
    Foo,
    Bar,
    Baz
}

fn example(e: Example) {
    match e {
        Example::Foo => println!("Foo"),
        Example::Bar | Example::Baz => {
            println!("Common code");
            // How can I avoid doing this?
            match e {
                Example::Bar => println!("Bar"),
                Example::Baz => println!("Baz"),
                _ => panic!()
            }
        }
    }
}

Extract it into a function.

2 Likes

Extract it into a function.

That's not really a solution, isn't it? Part of the problem is that I also need to use the _ pattern and treat that in some way, even if it is impossible to have other patterns except Bar and Baz in the nested match.

It is a solution. The most basic solution for code sharing is functions.

People are sometimes looking for clever tricks for code like that, but this is the simplest yet most understandable option.

Another alternative.

fn example(e: Example) {
    if matches!(e, Example::Bar | Example::Baz) {
        println!("Common code");
    }

    match e {
        Example::Foo => println!("Foo"),
        Example::Bar => println!("Bar"),
        Example::Baz => println!("Baz"),
    }
}
1 Like

To illustrate the function (or closure) approach:

enum Example {
    Foo,
    Bar,
    Baz
}

fn example(e: Example) {
    let common = || {
        println!("Common code");
    };
    match e {
        Example::Foo => println!("Foo"),
        Example::Bar => {
            common();
            println!("Bar");
        }
        Example::Baz => {
            common();
            println!("Baz");
        }
    }
}
1 Like

As I said, it is a contrived example. I can rewrite it like this, and still have the same problem, only now it is even less clear at a glance that I am expecting only certain patterns:

enum Example {
    Foo,
    Bar,
    Baz
}

fn handle_bar_or_baz(e: Example) {
    println!("Common code");
    match e {
        Example::Bar => println!("Bar"),
        Example::Baz => println!("Baz"),
        _ => panic!()
    }
}

fn example(e: Example) {
    match e {
        Example::Foo => handle_foo(),
        Example::Bar | Example::Baz => {
            handle_bar_or_baz(e)
        }
    }
}

No, what I meant is:

fn common_code() {
    println!("Common code");
}

fn example(e: Example) {
    match e {
        Example::Foo => println!("Foo"),
        Example::Bar => {
            common_code();
            println!("Bar");
        }
        Example::Baz => {
            common_code();
            println!("Baz");
        }
    }
}

Oh, right. This makes it clear. My main concern was the need for the _ pattern in the nested match. Thanks.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.