Можно ли написать функцию const, которая сворачивается поверх итератора? - PullRequest
0 голосов
/ 02 апреля 2019

Можно ли написать константную функцию, которая сворачивается поверх итератора? Когда я пытаюсь:

const fn foo(s: &str) -> u64 {
    return s.chars().fold(0, |accumulator, char| -> u64 {
        return accumulator ^ (char as u64);
    });
}

Я получаю ошибку компилятора:

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 | |     });
  | |_____^

Я предполагаю, что моя анонимная функция |x, y| -> x { ... } передается как указатель функции на fold(), и именно это вызывает ошибку.

Есть ли какая-то константная лямбда, которую я могу здесь передать fold, или я могу просто использовать цикл for и накапливать результат в изменяемой переменной, которую я затем возвращаю из функции foo? У меня нет абсолютно никакого опыта в Rust ...

1 Ответ

4 голосов
/ 02 апреля 2019

Нет, вы не можете сделать это в стабильной версии 1.33.Вам нужно будет сделать вашу функцию неконстантной:

fn foo(s: &str) -> u64 {
    s.chars().fold(0, |accumulator, char| {
        accumulator ^ (char as u64)
    })
}

Примечание. Я удалил явные ключевые слова return и возвращаемый тип закрытия как идиоматический.

См. Также:


Если вы попытаетесь сделать это в ночной Rust:

#![feature(const_fn)]

const fn foo(s: &str) -> u64 {
    s.chars().fold(0, |accumulator, char| {
        accumulator ^ (char as u64)
    })
}

Вы получите другую ошибку:

error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 --> src/lib.rs:4:5
  |
4 |     s.chars().fold(0, |accumulator, char| {
  |     ^^^^^^^^^

error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 --> src/lib.rs:4:5
  |
4 | /     s.chars().fold(0, |accumulator, char| {
5 | |         accumulator ^ (char as u64)
6 | |     })
  | |______^

Для вызова Iterator::fold требуется несколько расширений для оригинального const fn RFC 911 , чтобы бытьреализованы.Например, это явно запрещено оригинальным RFC:

Черты, реализации черт и их методы не могут быть const

Поскольку замыкания реализованы как универсальные элементы, поддерживаемые чертамиЯ не сразу вижу, что они могут быть легко реализованы по той же причине.

...