我正在尝试生成一个包含小写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`
这很奇怪,因为据我了解,这里有blanket implementation of Iterator
for RangeInclusive
。
是否可以将一系列字符用作迭代器?如果是这样,为什么?如果没有,我在做什么错?我正在使用稳定的Rust 2018 1.31.1。
答案 0 :(得分:7)
表达式b'a'..=b'z'
的类型为RangeInclusive<u8>
(see on Playground),因为表达式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
的界限很重要。如您在the documentation for Step
中所见,此特征是为所有原始整数类型实现的,而不是为char
实现的。这意味着对字符没有明确的“加一”操作。是的,您可以可以将其定义为下一个有效的Unicode代码点,但是Rust开发人员可能有充分的理由反对这一点。
因此, RangeInclusive<char>
未实现Iterator
。
因此您的解决方案已经是一个不错的解决方案。我可能会这样写:
(b'a'..=b'z').map(char::from).collect::<Vec<_>>()
唯一的真正好处是,在此版本中,char
不会出现两次。
答案 1 :(得分:2)
问题在于范围类型的迭代能力取决于Step
特征(see extended answer)。
但是,从Rust 1.45开始,char
还实现了Step
(PR 72413),这意味着问题中的代码现在可以正常工作!
let ascii_lowercase: Vec<char> = ('a'..='h').collect();
assert_eq!(
ascii_lowercase,
vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
);