macro_rules! vek { () => { ... }; ($($tail:tt)*) => { ... }; }
Expand description
A drop-in replacement for vec![]
that adds “spread” syntax.
let arr = [1, 2, 3];
let vec = vec![8, 9, 10];
assert_eq!(
vek![...arr, 4, ...(5..7), 7, ...vec],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
vek![a, b, c]
simply returns a vec of those elements, exactly like vec!
.
But elements can be prefixed with ...
to indicate a “spread”, which is
expanded by calling into_iter()
.
Examples
Normal vec!
syntax works the same way:
use lit_vek::vek;
assert_eq!(vek![1, 2, 3], vec![1, 2, 3]);
assert_eq!(vek!["x"; 5], vec!["x"; 5]);
Spread syntax [...xs]
inserts xs into the result via into_iter()
:
use lit_vek::vek;
let abc = [1, 2, 3];
assert_eq!(vek![...abc, ...abc], [1, 2, 3, 1, 2, 3]);
You can also use [...xs; n]
to repeat a sequence n times, like
std::iter::cycle()
but of finite length. The iterator returned
by xs.into_iter()
must implement Clone
.
use lit_vek::vek;
let abc = [1, 2, 3];
assert_eq!(
vek![...abc; 2], [1, 2, 3, 1, 2, 3])
And all these can be combined:
use lit_vek::vek;
let abc = [1, 2, 3];
// Note that (3..5) here is an ordinary range expression,
// not special syntax.
assert_eq!(
vek![1, ...[2;2], ...[...(3..5);2]],
[1, 2, 2, 3, 4, 3, 4]);
assert_eq!(
vek![0, ...[...abc; 2], ...[9; 3]],
[0, 1, 2, 3, 1, 2, 3, 9, 9, 9]);
The cycle-n-times logic is also available as a function, cycle_n
since it’s missing from std::iterator.
Design choices
Why ...
when most range-like things in Rust, including the existing
pattern spread syntax, use “..”? Because ..x
is already an expression
of type std::ops::RangeTo
. The macro could still work with ..
, and
you could disambiguiate by parenthesizing if necessary:
let r = [..1, ..2];
let my_ranges = vek![(..1), ..r];
But it seemed better to sidestep the issue.
Why prefix instead of suffix syntax, like vek![a, bs..., c]
? Mostly
to match other languages I’m aware of with spread syntax.
See also
The iter![]
macro in this crate uses the same syntax, but produces
an iterator instead of a Vec. In fact vek![...]
is equivalent to
iter![...].collect::<Vec<_>>()
.