In Rust, it is possible to iterate over values of an array:
const COOL_NUMBERS: [i32; 4] = [1, 3, 3, 7];
fn do_something_cool() {
for number in COOL_NUMBERS {
// ...
}
}
But it is not possible to do in const
context (at least not on stable):
const COOL_NUMBERS: [i32; 4] = [1, 3, 3, 7];
const fn do_something_cool() {
for number in COOL_NUMBERS {
// ...
}
}
error[E0015]: cannot convert `[i32; 4]` into an iterator in constant functions
--> src/lib.rs:4:19
|
4 | for number in COOL_NUMBERS {
| ^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
...
See playground link for full list of errors.
I know that it is possible to do things like this to sidestep the error:
const COOL_NUMBERS: [i32; 4] = [1, 3, 3, 7];
const fn do_something_cool() {
do_for_loop(&COOL_NUMBERS)
}
const fn do_for_loop(numbers: &[i32]) {
match numbers {
[] => {}
[number, rest @ ..] => {
// ...
do_for_loop(rest);
}
}
}
But frankly, this looks horrible, isn't there a better way?
So, my question is:
Is there a cleaner way to const
-iterate over an array in stable?
Is there at least a cleaner way to const
-iterate over an array in unstable?
Are there any crates that help with doing this?
After some more searching I found out that it's possible to do this in stable:
const COOL_NUMBERS: [i32; 4] = [1, 3, 3, 7];
const fn do_something_cool() {
let mut i = 0;
while i < COOL_NUMBERS.len() {
let number = COOL_NUMBERS[i];
// ...
i += 1;
}
}
If you need a crate to work with const
Iterator
s, you may use konst. Here's an example from konst docs:
use konst::iter::{ConstIntoIter, IsIteratorKind};
struct Upto10(u8);
impl ConstIntoIter for Upto10 {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = u8;
}
impl Upto10 {
const fn next(mut self) -> Option<(u8, Self)> {
if self.0 < 10 {
let ret = self.0;
self.0 += 1;
Some((ret, self))
} else {
None
}
}
}
const N: u32 = {
let mut n = 0u32;
konst::iter::for_each!{elem in Upto10(7) =>
n = n * 10 + elem as u32;
}
n
};
assert_eq!(N, 789);