我正在尝试生成一个包含小写 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。
最佳答案
编辑 2020-07-17:自 Rust 1.45.0 以来,特征 Step
为 char
实现, 制作 Range<char>
(和其他一些字符范围)作为迭代器工作。问题中的代码现在编译没有问题!
下面是旧答案。
表达式b'a'..=b'z'
类型为 RangeInclusive<u8>
( see on Playground ) 因为表达式 b'a'
类型为 u8
: 这就是b
字面量前面的是for。另一方面,表达式 'a'..='z'
(没有 b
s)具有类型 RangeInclusive<char>
.
[...] there is a blanket implementation of
Iterator
forRangeInclusive
.
首先,这不是我们所说的“一揽子实现”(这是当 impl block 是 for T
或 for &T
(或类似的),其中 T
是泛型类型时)。但是,是的,有一个暗示。但让我们仔细看看:
impl<A> Iterator for RangeInclusive<A>
where
A: Step, // <--- important
A: Step
绑定(bind)很重要。正如您在 the documentation for Step
中看到的那样,此特征适用于所有原始整数类型,但不适用于 char
.这意味着对字符没有明确的“加一”操作。是的,您可以将其定义为下一个有效的 Unicode 代码点,但 Rust 开发人员可能出于充分的理由决定不这样做。
因此, RangeInclusive<char>
不执行 Iterator
.
所以您的解决方案已经是一个很好的解决方案。我可能会这样写:
(b'a'..=b'z').map(char::from).collect::<Vec<_>>()
唯一真正的优势是在这个版本中,char
不会出现两次。
关于collections - 为什么不能收集一系列字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53971954/