arrayvec
arrayvec copied to clipboard
A vec! like macro
Maybe arrvec! or arr_vec! ?
We already have ArrayVec::from([array literal here])
which serves this purpose quite well, not sure what the benefits of a macro are.
@bluss The macro allows you to concisely initialize an arrayvec with a potentially larger backing store.
Say I have the following type code:
type StorageType = ArrayVec<[u64; 20]>;
pub fn main() {
// This fails, due to mismatched types, expected an array with 20 elements, got an array with 1 element.
let s: StorageType = ArrayVec::from([1]);
}
There's no really good way to initialize from a macro without copying, but a simple way to implement an arrayvec macro would be:
#[macro_export]
macro_rules! arrvec {
// This only works if the ArrayVec is the same size as the input array.
($elem:expr; $n:expr) => ({
$crate::ArrayVec::from([$elem; $n])
});
// This just repeatedly calls `push`. I don't believe there's a concise way to count the number of expressions.
($($x:expr),*$(,)*) => ({
// Allow an unused mut variable, since if the sequence is empty,
// the vec will never be mutated.
#[allow(unused_mut)] {
let mut vec = $crate::ArrayVec::new();
$(vec.push($x);)*
vec
}
});
}
Please feel free to use that code.
If you'd like to count the number of elements, and then directly initialize and set the length, you could likely do that with:
macro_rules! count {
() => (0usize);
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
}
However, you'd likely have to use a for loop to assign by index, because I don't believe there's a generic way to count the number of elements you'd have to pad the array with using a macro, which pretty much defeats the purpose.
Interesting. Counting expressions -- see the little book of rust macros, or the maplit macros. But is not needed - you can write it to use extend with an exact size arrayvec into the inferred size one. That's kind of nice.
@Alexhuszagh I've thought about this, and
-
To be efficient, that macro needs a method that implements something like this:
ArrayVec::<[_; 128]>::from_array([1, 2, 3, 4])
which allows starting with a shorter array than the full capacity. And that's easy and efficient to implement. We avoid push, which would be slow. Main challenge I see here is to give it a name, because justfrom
is already taken :slightly_smiling_face: -
Then we have a method that serves the purpose and don't need a macro. Macros are only necessary when we can't express it with regular methods.
You can use this: https://crates.io/crates/array-macro E.g.:
ArrayVec::from(array![vec![]; 16])
But it may not be in-place (may move the whole array)..
I think such a macro would be nice, even if the only advantage was that it made arrayvec work more like Vec and SmallVec. This would make it easier to remember how to construct an "ArrayVec literal".
@Alexhuszagh What about ArrayVec::from_iter([x])
?
Wouldn't it result in very optimized code?