Is there a way to use closures or list comprehension when defining constant arrays in Rust? Suppose we have these three const arrays:
const K1 : [i32;8] = [100, 100, 101, 102, 104, 106, 108, 900];
const K2 : [i32;8] = [-100, -100, -101, -102, -104, -106, -108, -900];
const K3 : [i32;8] = [-900, -108, -106, -104, -102, -101, -100, -100];
In python K2 and K3 could be expressed as
K2=[-x for x in K1]
K3=[-x for x in K1[::-1]
Rust has the cute crate which emulates python list comprehension, but I don't think it can be used to define constants. So is there a more elegant solution than simply typing out K2 and K3 as above?
Someday, when Rust has more constant-evaluation abilities, we may be able to write the following:
const K1: [i32; 8] = [100, 100, 101, 102, 104, 106, 108, 900];
const K2: [i32; 8] = K1.map(|x| -x);
const K3: [i32; 8] = { let mut a = K2; a.reverse(); a };
However, for now, neither array::map() nor slice::reverse() are const fns, so you can't use them in constants. map in particular is going to be more trouble because it requires the ability to define higher-order const fns which is not yet available.
However, we can define our own const functions to do the specific jobs we need. This requires a lot more code, so it's not a great idea if you have only one case, but it could be worthwhile anyway to help readability of the constant definitions, or if these situations come up more than once.
const K1: [i32; 8] = [100, 100, 101, 102, 104, 106, 108, 900];
const K2: [i32; 8] = array_i32_mul(-1, K1);
const K3: [i32; 8] = array_reverse(K2);
const fn array_i32_mul<const N: usize>(factor: i32, mut a: [i32; N]) -> [i32; N] {
let mut i = 0;
while i < N {
a[i] *= factor;
i += 1;
}
a
}
const fn array_reverse<T: Copy, const N: usize>(mut a: [T; N]) -> [T; N] {
let mut i = 0;
while i < N / 2 {
let from_end = N - i - 1;
(a[i], a[from_end]) = (a[from_end], a[i]);
i += 1;
}
a
}
fn main() {
dbg!(K1, K2, K3);
}
Notes:
for loops in const fns yet, because traits aren't supported and for uses Iterator which is a trait, so we have to use while for all our indexing.array_reverse would not need T: Copy if std::mem::swap() were const, but it isn't yet.The advantages of going to this effort over using Lazy, as suggested in another answer, are:
Lazy accessing the value is only possible at run time.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With