Is it possible to write a const function that folds over an iterator? When I try:
const fn foo(s: &str) -> u64 {
return s.chars().fold(0, |accumulator, char| -> u64 {
return accumulator ^ (char as u64);
});
}
I get a compiler error:
error: function pointers in const fn are unstable
--> src/lib.rs:2:30
|
2 | return s.chars().fold(0, |accumulator, char| -> u64 {
| ______________________________^
3 | | return accumulator ^ (char as u64);
4 | | });
| |_____^
I presume that my anonymous function |x, y| -> x { ... }
is passed as a function pointer to fold()
and that's what's causing the error.
Is there some kind of const lambda that I can pass to fold
here, or can I just use a for loop instead and accumulate the result in a mutable variable which I then return from the foo
function? I have absolutely no Rust experience...
No, you cannot do this in stable Rust 1.59. You will need to make your function non-const:
fn foo(s: &str) -> u64 {
s.chars().fold(0, |accumulator, char| {
accumulator ^ (char as u64)
})
}
Note I removed the explicit return
keywords and closure return type to be idiomatic.
See also:
If you attempt this in nightly Rust:
const fn foo(s: &str) -> u64 {
s.chars().fold(0, |accumulator, char| {
accumulator ^ (char as u64)
})
}
You'll get a different error:
error[E0015]: cannot call non-const fn `core::str::<impl str>::chars` in constant functions
--> src/lib.rs:2:7
|
2 | s.chars().fold(0, |accumulator, char| {
| ^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<Chars as Iterator>::fold::<u64, [closure@src/lib.rs:2:23: 4:6]>` in constant functions
--> src/lib.rs:2:15
|
2 | s.chars().fold(0, |accumulator, char| {
| _______________^
3 | | accumulator ^ (char as u64)
4 | | })
| |______^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
Calling Iterator::fold
requires several extensions to the original const fn
RFC 911 to be implemented. For example, it's expressly forbidden by the original RFC:
Traits, trait implementations and their methods cannot be
const
Since closures are implemented as generics backed by traits, I don't immediately see that they could be easily implemented for the same reason.