Почему нельзя собрать диапазон символов? - PullRequest
0 голосов
/ 29 декабря 2018

Я пытаюсь создать вектор, содержащий строчные буквы ASCII.Этот более запутанный подход работает:

let ascii_lowercase = (b'a'..=b'z').map(|b| b as char).collect::<Vec<char>>();

Но этот более простой подход, который я придумал в первую очередь, не:

let ascii_lowercase = ('a'..='z').collect::<Vec<char>>();

Ошибка:

error[E0599]: no method named `collect` found for type `std::ops::RangeInclusive<char>` in the current scope
 --> src/main.rs:2:39
  |
2 |     let ascii_lowercase = ('a'..='z').collect::<Vec<char>>();
  |                                       ^^^^^^^
  |
  = note: the method `collect` exists but the following trait bounds were not satisfied:
          `std::ops::RangeInclusive<char> : std::iter::Iterator`
          `&mut std::ops::RangeInclusive<char> : std::iter::Iterator`

Что странно, потому что, насколько я понимаю, существует общая реализация Iterator для RangeInclusive.

Разве невозможно использовать диапазонсимволов как итератор?Если так, то почему?Если нет, что я делаю не так?Я использую стабильный Rust 2018 1.31.1.

1 Ответ

0 голосов
/ 29 декабря 2018

Выражение b'a'..=b'z' имеет тип RangeInclusive<u8> ( см. На игровой площадке ), потому что выражение b'a' имеет тип u8: это то, что b перед литералом символадля.С другой стороны, выражение 'a'..='z' (без b s) имеет тип RangeInclusive<char>.

[...] есть общая реализация Iterator для RangeInclusive.

Во-первых, это не то, что мы называем «общей реализацией» (это когда блок impl равен for T или for &T (или аналогичным), а T являетсяуниверсальный тип).Но да, есть импл.Но давайте внимательнее посмотрим:

impl<A> Iterator for RangeInclusive<A> 
where
    A: Step,   // <--- important

Граница A: Step важна.Как вы можете видеть в документации для Step, эта черта реализована для всех примитивных целочисленных типов, но не для char.Это означает, что не существует четкой операции «добавить один» для символов.Да, вы могли бы определить, что это будет следующий допустимый код Unicode, но разработчики Rust, вероятно, отказались от этого по уважительной причине.

Как следствие, RangeInclusive<char> делаетне реализовать Iterator.

Так что ваше решение уже хорошее.Я бы, наверное, написал так:

(b'a'..=b'z').map(char::from).collect::<Vec<_>>()

Единственное реальное преимущество в том, что в этой версии char не появляется дважды.

...