ideasman42
ideasman42

Reputation: 48198

How to avoid repetition expanding indices with macros in Rust?

Is there a way to write this macro that expands array access in such a way that larger arrays can be written in a less verbose way?

/// 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]} } };
}

Upvotes: 0

Views: 781

Answers (1)

lukwol
lukwol

Reputation: 264

To reduce verbosity you can construct recursive macro.

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]));
}

Every macro can be called with (), [] and {} brackets, so if you don't need additional pair of brackets your macro can be as simple as that:

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]);
}

Example from Rust Book.

Upvotes: 2

Related Questions