Macro pick

Source
pick!() { /* proc-macro */ }
Expand description

Pick some elements from a tuple.

§Syntax

IndicesGroup      = Index [ - Index ]

pick!(Expr; IndicesGroup1 [, IndicesGroup2, ...] )

[ and ] only indicate the optional content but not that they need to be input.

Similarly, ... indicates several repeated segments, rather than inputting ....

The index must be an integer literal since procedural macros do not yet support evaluating constants.

§Explanation

The pick! macro allows you to pick some elements you want from a tuple to a new tuple, and the unpicked elements will be put into a new tuple.

use tuplez::{pick, tuple};

let tup = tuple!(1, "hello", 3.14, [1, 2, 3], Some(9.8), 'c');
let (picked, unpicked) = pick!(tup; 3, 1, 5);
assert_eq!(picked, tuple!([1, 2, 3], "hello", 'c'));
assert_eq!(unpicked, tuple!(1, 3.14, Some(9.8)));

You can abbreviate the continuous part as start - end:

use tuplez::{pick, tuple};

let tup = tuple!(1, "hello", 3.14, [1, 2, 3], Some(9.8), 'c');
let (picked, unpicked) = pick!(tup; 4, 1-3);
assert_eq!(picked, tuple!(Some(9.8), "hello", 3.14, [1, 2, 3]));
assert_eq!(unpicked, tuple!(1, 'c'));

Of course, reverse ranges are also supported:

use tuplez::{pick, tuple};

let tup = tuple!(1, "hello", 3.14, [1, 2, 3], Some(9.8), 'c');
let (picked, unpicked) = pick!(tup; 4, 3-1);    // `3-1` is reverse range
assert_eq!(picked, tuple!(Some(9.8), [1, 2, 3], 3.14, "hello"));
assert_eq!(unpicked, tuple!(1, 'c'));

If Rust’s move checker allows it, then you can pick the same element multiple times:

use tuplez::{pick, tuple};

let tup = tuple!(1, "hello", 3.14, [1, 2, 3], Some(9.8), 'c');
let (picked, unpicked) = pick!(tup; 1, 1, 1, 5, 5);
assert_eq!(picked, tuple!("hello", "hello", "hello", 'c', 'c'));
assert_eq!(unpicked, tuple!(1, 3.14, [1, 2, 3], Some(9.8)));

Another common use is when you want to pick references to some elements of the original tuple:

use tuplez::{get, pick, tuple, TupleLike};

let mut tup = tuple!(1, "hello", 3.14, [1, 2, 3], Some(9.8), 'c');
let (picked, _) = pick!(tup.as_mut(); 3, 0);
get!(picked; 0).rotate_left(1);
*get!(picked; 1) += 100;
assert_eq!(tup, tuple!(101, "hello", 3.14, [2, 3, 1], Some(9.8), 'c'));

NOTE: Unlike take!, even if you pick! only one element, you still get a tuple.