2017-02-20 11 views
9

Chcę sprawdzić, jeśli ciąg zawiera '$', a jeśli coś jest nie po '$':Czy można połączyć dwa wzory, jeden ze strażnikiem meczowym, w tym samym ramieniu meczowym?

Próbowałem ten kod:

fn test(s: String) { 
    match s.find('$') { 
     None | (Some(pos) if pos == s.len() - 1) => { 
      expr1(); 
     } 
     _ => { expr2(); } 
    } 
} 

Ale to nie kompiluje:

error: expected one of `)` or `,`, found `if` 

Czy da się połączyć None i Some w jednym meczu ramienia?

Jeśli tak, czy istnieje prosty sposób, aby nie powielać numeru expr1(), z wyjątkiem przeniesienia go do oddzielnej funkcji?

Odpowiedz

7

Jest niemożliwe mieć match-strażnika (the if thingy) stosuje się tylko do jednej alternatywie wzoru (rzeczy oddzielone | symboli). Jest tylko jeden strażnik na ramię i ma on zastosowanie do wszystkich wzorów tego ramienia.

Istnieje jednak wiele rozwiązań dla konkretnego problemu. Na przykład:

if s.find('$').map(|i| i != s.len() - 1).unwrap_or(false) { 
    expr2(); 
} else { 
    expr1(); 
} 
+3

Działa to, ale polega na tym, że '$' jest ASCII i tym samym zajmuje jeden bajt. Bardziej ogólne rozwiązanie może wykorzystywać ['char :: len_utf8'] (https://doc.rust-lang.org/std/primitive.char.html#method.len_utf8):' i! = S.len() - "c'.len_utf8()'. – Shepmaster

+2

Chcę wejść do kodu golfowego: 's.chars(). Skip_while (| i | i! = '$'). Skip (1) .next(). Is_some()' jest dużo jaśniejsze niż jakiekolwiek obliczenia indeksu imo –