2017-10-15 10 views
1

私はそれが必要でない場合は、それらのすべてを呼び出すことなく、いくつかの関数の結果と一致するようにしたい:パターンマッチング時に冗長な関数呼び出しを避けるには?

fn foo() -> bool { 
    println!("foo executed"); 
    true 
} 

// I want to do something like this 
// but there is a redundant function call 
match (foo(), foo()) { 
    (false, true) => println!("Bingo!"), 
    _ => println!("Wrong result"), 
} 

// No redundant function call 
// but less impressive and doubling of wrong result processing 
match foo() { 
    false => match foo() { 
     true => println!("Bingo"), 
     _ => println!("Wrong result"), 
    }, 
    _ => println!("Wrong result"), 
} 

はどうすればこれを行うことができますか?

答えて

2

私はマクロを使って第二のアプローチを美しくできることが分かった:

macro_rules! lazy_match { 
    (($condition:expr => $expect:pat) => $on_expected:expr, _ => $other:expr) => (
     match $condition { 
      $expect => $on_expected, 
      _ => $other, 
     } 
    ); 
    (
     ($condition:expr => $expect:pat, $($c:expr => $e:pat),+) 
     => $on_expected:expr, _ => $other:expr 
    ) => (
     match $condition { 
      $expect => lazy_match!(($($c => $e),+) => $on_expected, _ => $other), 
      _ => $other, 
     } 
    ); 
} 

lazy_match! { 
    (foo() => false, foo() => true) => println!("Bingo"), 
    _ => println!("Wrong result") 
}; 
3

は、あなたは、単に行うことができます。

if !foo() && foo() { println!("Bingo") } else { println!("Wrong result") } 

"と"(&&)と "または"(||) Rustの論理演算子は、ほとんどの言語と同様に短絡しています。 !foo()ので

&&の右側が評価されず、foo()を2回呼び出されない、falseです。 あなたのマクロソリューションは、基本的に、少なくともこのおもちゃの例では短絡を再発明しています(実際のコードではもっと読みやすくなります)。

関連する問題