admin管理员组

文章数量:1245032

I have a match block that determines who needs to send a message

match text.to_id {
            Some(id)  => {
                if let Some(tx) = state.read().unwrap().get(&id){
                    tx.send(message.clone()).unwrap();
                } else {continue;}
            } 
            None  => {
                for (_id, send) in state.read().unwrap().iter(){
                    send.send(message.clone()).unwrap();
                }
            }
        }

but if id == 0, this should send the message to everyone the same way. if I try:

None | Some(0)=>
None | Some(id) if id == 0=>

or

Some(id) if id !=0 =>

it doesn't work or send me a error:

`Some(_)` not covered

how can use pattern None too, if id==0?

I have a match block that determines who needs to send a message

match text.to_id {
            Some(id)  => {
                if let Some(tx) = state.read().unwrap().get(&id){
                    tx.send(message.clone()).unwrap();
                } else {continue;}
            } 
            None  => {
                for (_id, send) in state.read().unwrap().iter(){
                    send.send(message.clone()).unwrap();
                }
            }
        }

but if id == 0, this should send the message to everyone the same way. if I try:

None | Some(0)=>
None | Some(id) if id == 0=>

or

Some(id) if id !=0 =>

it doesn't work or send me a error:

`Some(_)` not covered

how can use pattern None too, if id==0?

Share Improve this question edited Feb 15 at 17:04 cafce25 27.5k5 gold badges44 silver badges55 bronze badges asked Feb 15 at 9:46 kecakisakecakisa 411 silver badge4 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 4

Patterns are traversed top-to-bottom. So if you add alternates to the None clause (overlapping with the Some() clause) you need to move the pattern to the top:

match text.to_id {
    None | Some(0) => {
        for (_id, send) in state.read().unwrap().iter(){
            send.send(message.clone()).unwrap();
        }
    }
    Some(id)  => {
        if let Some(tx) = state.read().unwrap().get(&id){
            tx.send(message.clone()).unwrap();
        } else {continue;}
    } 
}

If you add a guard to the original Some clause, then you still need to match Some(_) in the bottom clause for Some(0) and Rust does not have refinement types so it does not understand that the complement of Some(id) if id != 0 is Some(0), which is why it's telling you that Some(_) is not covered. In that case the easiest is to just use a wildcard for the second branch

match text.to_id {
    Some(id) if id != 0 => {
        if let Some(tx) = state.read().unwrap().get(&id){
            tx.send(message.clone()).unwrap();
        } else {continue;}
    } 
    _ => {
        for (_id, send) in state.read().unwrap().iter(){
            send.send(message.clone()).unwrap();
        }
    }
}

An other alternative is to fold the Some(0) case into a None via Option::filter, such that the case does not "infect" the match:

match text.to_id.filter(|id| *id != 0) {
    Some(id) => {
        if let Some(tx) = state.read().unwrap().get(&id){
            tx.send(message.clone()).unwrap();
        } else {continue;}
    } 
    None => {
        for (_id, send) in state.read().unwrap().iter(){
            send.send(message.clone()).unwrap();
        }
    }
}

本文标签: rustmatch Optionltgt with many patterns and 1 conditionalStack Overflow