Say we need to declare a fixed size array with values, where the size of the array is defined by a constant that may change depending on compile time settings.
So for example:
let my_array = expand_into_array!(j, ARRAY_SIZE, -v0[j] * f);
Where ARRAY_SIZE
is a constant, for example:
const ARRAY_SIZE: usize = 3;
Could expand into something like...
let my_array = [
{let j = 0; {-v0[j] * f}},
{let j = 1; {-v0[j] * f}},
{let j = 2; {-v0[j] * f}},
];
Since the expression is a fixed size array, it may be possible to use pattern matching, for a limited number of items ... up to 32 for example.
Is it possible to write a macro that expands an expression N times, based on a constant integer?
Details...
Looking into this, I wrote a macro which defines an array, then fills it in, eg:
const ARRAY_SIZE: usize = 3;
macro_rules! expand_into_array {
($index_var:ident, $const_size:expr, $body:expr) => {
{
let mut tmp: [_; $const_size] = [0.0; $const_size];
for $index_var in 0..$const_size {
tmp[$index_var] = $body;
}
// TODO, check $body _never_ breaks.
tmp
}
}
}
pub fn negated_array(v0: &[f64; ARRAY_SIZE]) -> [f64; ARRAY_SIZE] {
expand_into_array!(j, ARRAY_SIZE, {
-v0[j]
})
}
This works as expected, and besides the wrinkle (that the $body
expression could include a break
). this works without problems.
However initializing the array to 0.0 isn't getting optimized out (changing this value shows up as changes when run with:
cargo rustc --release -- --emit asm
I'd rather not use unsafe { std::mem::uninitialized }
.
Update, from asking another question, it seems macros can only match against literals, and not constants.
So this is simply not possible with macros in Rust.