Skip to content

Instantly share code, notes, and snippets.

@Mr-Byte
Created December 29, 2014 19:25
Show Gist options
  • Save Mr-Byte/5257de73660630d236d2 to your computer and use it in GitHub Desktop.
Save Mr-Byte/5257de73660630d236d2 to your computer and use it in GitHub Desktop.
#![feature(macro_rules)]
macro_rules! active_match {
//Zero parameter case followed by one or more cases
($m:expr, $i:ident() => $b:block $(, $i_rest:ident($($ps_rest:pat),*) => $b_rest:block)+) => {
match $i($m) {
Some(()) => $b,
None => active_match! { $m, $($i_rest($($ps_rest),*) => $b_rest),+ }
}
};
//One parameter case followed by one or more cases
($m:expr, $i:ident($p:pat) => $b:block $(, $i_rest:ident($($ps_rest:pat),*) => $b_rest:block)+) => {
match $i($m) {
Some($p) => $b,
None => active_match! { $m, $($i_rest($($ps_rest),*) => $b_rest),+ }
}
};
//Multiple parameter case followed by one or more cases
($m:expr, $i:ident($($ps:pat),*) => $b:block $(, $i_rest:ident($($ps_rest:pat),*) => $b_rest:block)+) => {
match $i($m) {
Some(($($ps),*)) => $b,
None => active_match! { $m, $($i_rest($($ps_rest),*) => $b_rest),+ }
}
};
//Single zero parameter case
($m:expr, $i:ident() => $b:block) => {
match $i($m) {
Some(()) => $b,
None => panic!("Encountered an unmatched active case.")
}
};
//Single one parameter case
($m:expr, $i:ident($p:pat) => $b:block) => {
match $i($m) {
Some($p) => $b,
None => panic!("Encountered an unmatched active case.")
}
};
//Single multiple parameter case
($m:expr, $i:ident($($ps:pat),*) => $b:block) => {
match $i($m) {
Some(($($ps),*)) => $b,
None => panic!("Encountered an unmatched active case.")
}
};
//Zero parameter case followed by a wildcard.
($m:expr, $i:ident() => $b:block, _ => $b_rest_default:block) => {
match $i($m) {
Some(()) => $b,
None => $b_rest_default
}
};
//One parameter case followed by a wildcard.
($m:expr, $i:ident($p:pat) => $b:block, _ => $b_rest_default:block) => {
match $i($m) {
Some($p) => $b,
None => $b_rest_default
}
};
//Multiple parameter case followed by a wildcard.
($m:expr, $i:ident($($ps:pat),*) => $b:block, _ => $b_rest_default:block) => {
match $i($m) {
Some(($($ps),*)) => $b,
None => $b_rest_default
}
};
//Zero parameter case followed by one or more cases and a wildcard.
($m:expr, $i:ident() => $b:block $(, $i_rest:ident($($ps_rest:pat),*) => $b_rest:block)+, _ => $b_rest_default:$block) => {
match $i($m) {
Some(()) => $b,
None => active_match! { $m, $($i_rest($($ps_rest),*) => $b_rest),+, _ => $b_rest_default }
}
};
//One parameter case followed by one or more cases and a wildcard.
($m:expr, $i:ident($p:pat) => $b:block $(, $i_rest:ident($($ps_rest:pat),*) => $b_rest:block)+, _ => $b_rest_default:$block) => {
match $i($m) {
Some($p) => $b,
None => active_match! { $m, $($i_rest($($ps_rest),*) => $b_rest),*+ _ => $b_rest_default }
}
};
//Multiple parameter case followed by one or more cases and a wildcard.
($m:expr, $i:ident($($ps:pat),*) => $b:block $(, $i_rest:ident($($ps_rest:pat),*) => $b_rest:block)+, _ => $b_rest_default:$block) => {
match $i($m) {
Some(($($ps),*)) => $b,
None => active_match! { $m, $($i_rest($($ps_rest),*) => $b_rest),+, _ => $b_rest_default }
}
};
//Single wild card case
($m:expr, _ => $b:block) => {
$b
};
}
fn is_even(n: i32) -> Option<()> {
if n % 2 == 0 { Some(()) } else { None }
}
fn is_odd(n: i32) -> Option<()> {
if n % 2 == 1 { Some(()) } else { None }
}
fn double_up(n:i32) -> Option<i32> {
Some(n*2)
}
fn double_and_triple_if_even(n: i32) -> Option<(i32, i32)> {
if n % 2 == 0 {
Some((n*2, n*3))
} else {
None
}
}
fn main() {
println!("Testing two cases with no parameters.");
for i in range(1,10) {
active_match! { i,
is_even() => { println!("{} is an even number.", i) },
is_odd() => { println!("{} is an odd number.", i) }
}
}
println!("----");
println!("Testing one case with no parameters and a wildcard.");
for i in range(1,10) {
active_match! { i,
is_even() => { println!("{} is an even number.", i) },
_ => { println!("{} is an odd number.", i) }
}
}
println!("----");
println!("Testing one case with one parameter.");
for i in range(1,10) {
active_match! { i,
double_up(n) => { println!("{} doubled is {}.", i, n) }
}
}
println!("----");
println!("Testing one case with two parameters and a wildcard.");
for i in range(1,10) {
active_match! { i,
double_and_triple_if_even(n2, n3) => { println!("{} doubled is {}, and tripled is {}.", i, n2, n3) },
_ => { println!("{} is odd.", i); }
}
}
println!("----");
println!("Testing one case with two parameters, one case with a pattern and a parameter, and a wildcard.");
for i in range(1,10) {
active_match! { i,
double_and_triple_if_even(4, n3) => { println!("Two doubled is {}, and tripled is {}.", n2, n3) },
double_and_triple_if_even(n2, n3) => { println!("{} doubled is {}, and tripled is {}.", i, n2, n3) },
_ => { println!("{} is odd.", i); }
}
}
println!("----");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment