collections - リスト内包表記マクロ

macro_rules! list {
    ($($t:tt)*) => {{ let mut r = vec![]; list_inner!(r, $($t)*); r }}
}
macro_rules! list_inner {
    ($r:expr) => {};
    ($r:expr, $e:expr) => { $r.push($e) };
    ($r:expr, $e:expr;) => { $r.push($e) };
    ($r:expr, $e:expr; for $k:ident in $range:expr) => { for $k in $range { list_inner!($r, $e) } };
    ($r:expr, $e:expr; if $cond:expr) => { if $cond { list_inner!($r, $e) } };
    ($r:expr, $e:expr; for $k:ident in $range:expr ; $($t:tt)*) => { for $k in $range { list_inner!($r, $e ; $($t)*); } };
    ($r:expr, $e:expr; if $cond:expr ; $($t:tt)*) => { if $cond { list_inner!($r, $e ; $($t)*); } };
}

使い方

list! {
    (expression);
    $(
        (for-range);
        (if-condition);
    );*
}

式間の区切りは全てセミコロン (;). 一番最後のセミコロンはあっても無くても良い.

list! {
    x;
    for x in 0..10
}
list! {
    x;
    for x in 0..10;
    if x % 2 == 0
}

forif は上から順に実行される. 必要ならば早めに if でフィルタできる.

list! {
    (x, y);
    for x in 0..10;
    if x % 2 == 0;
    for y in x..20;
    if y % 2 == 0
}
list! {
    (x, y, z);
    for x in 1..100;
    for y in x..100;
    for z in y..x + y;
    if x * x + y * y == z * z;
}