如何避免在Rust中使用宏重复扩展索引?

时间:2016-12-31 16:53:11

标签: macros rust

有没有办法编写这个扩展数组访问的宏,以便能够以更简洁的方式编写更大的数组?

/// Avoid manually expanding an expression, eg:
///
/// let array =  unpack!([some.vec; 3]);
///
/// Expands into: [some.vec[0], some.vec[1], some.vec[2]]
///
/// Supports expanding into different bracket types based on the input args.

macro_rules! unpack {
    ([$v_:expr; 2]) => { { let v = $v_; [v[0], v[1]] } };
    (($v_:expr; 2)) => { { let v = $v_; (v[0], v[1]) } };
    ({$v_:expr; 2}) => { { let v = $v_; {v[0], v[1]} } };

    ([$v_:expr; 3]) => { { let v = $v_; [v[0], v[1], v[2]] } };
    (($v_:expr; 3)) => { { let v = $v_; (v[0], v[1], v[2]) } };
    ({$v_:expr; 3}) => { { let v = $v_; {v[0], v[1], v[2]} } };

    ([$v_:expr; 4]) => { { let v = $v_; [v[0], v[1], v[2], v[3]] } };
    (($v_:expr; 4)) => { { let v = $v_; (v[0], v[1], v[2], v[3]) } };
    ({$v_:expr; 4}) => { { let v = $v_; {v[0], v[1], v[2], v[3]} } };
}

1 个答案:

答案 0 :(得分:2)

要减少冗长,可以构造递归宏。

macro_rules! unpack {
    ({$vec:expr; $count:expr}) => { 
        unpack!([$vec; $count])
    };
    (($vec:expr; $count:expr)) => { 
        unpack!([$vec; $count])
    };
    ([$vec:expr; $count:expr]) => { 
        $vec[0..$count]
    };
}

fn main() {
    let vec = vec![1, 2, 3, 4, 5];
    assert_eq!([1, 2], unpack!({vec; 2}));
    assert_eq!([1, 2, 3], unpack!((vec; 3)));
    assert_eq!([1, 2, 3, 4], unpack!([vec; 4]));
}

可以使用()[]{}括号调用每个宏,因此如果您不需要额外的括号对,那么您的宏可以像这样简单:

macro_rules! unpack {
    ($vec:expr; $count:expr) => { 
        $vec[0..$count]
    };
}

fn main() {
    let vec = vec![1, 2, 3, 4, 5];
    assert_eq!([1, 2], unpack!{vec; 2});
    assert_eq!([1, 2, 3], unpack!(vec; 3));
    assert_eq!([1, 2, 3, 4], unpack![vec; 4]);
}
来自Rust Book的

Example