1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
/*!
Rust crate that defines macros to enable ES-like "spread" syntax for
literal sequences.
```rust
# use lit_vek::{iter,vek};
let arr = [4, 5, 6];
// `vek!` is a drop-in replacement for `std::vec!`, except you can
// use `...x` to expand iterables.
assert_eq!(
vek![1, 2, 3, ...arr, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!(
vek![1, 2, 3, ...arr, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9]);
// `iter!` provides the same syntax as iterator, similar to
// itertools::chain()
# use std::collections::VecDeque;
let d: VecDeque<_> = iter![1, 2, 3, ...arr, 7, 8, 9].collect();
```
*/
mod iter;
pub use iter::{cycle_n, CycleN};
/**
A drop-in replacement for `vec![]` that adds "spread" syntax.
# use {lit_vek::vek, std::array};
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:
```ignore
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<_>>()`.
*/
#[macro_export]
macro_rules! vek {
() => { Vec::new() };
($($tail:tt)*) => {
::std::iter::Iterator::collect::<Vec<_>>($crate::iter![$($tail)*])
};
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let empty: Vec<u32> = vek![];
println!("{:?}", empty);
println!("{:?}", vek![1]);
println!("{:?}", vek![...[1,2]]);
println!("{:?}", vek![1, 2, 3, ...[4, 5], 6,...[7, 8]]);
let temp = vec![2, 3, 4];
println!("{:?}", vek![1, ...temp.iter().copied(), 5, 6]);
}
}