问题描述
为什么以下带有字符范围的 for 循环无法编译?
Why does the following for loop with a char range fail to compile?
fn main() {
for c in 'a'..'z' {
println!("{}", c);
}
}
错误...
main.rs:11:5: 14:2 error: the trait `core::num::One` is not implemented for the type `char` [E0277]
main.rs:11 for c in 'a'..'z' {
main.rs:12 println!("{}", c);
main.rs:13 }
main.rs:14 }
main.rs:11:5: 14:2 error: the trait `core::iter::Step` is not implemented for the type `char` [E0277]
main.rs:11 for c in 'a'..'z' {
main.rs:12 println!("{}", c);
main.rs:13 }
main.rs:14 }
为什么你甚至需要 core::num::One
来迭代一个范围?
Why do you even need core::num::One
for a iterating over a range?
推荐答案
x..y
语法是 std::ops::Range { 开始:x,结束:y }
.这种类型(Range
)是可迭代的,因为它实现了 Iterator
,特别是从那个页面:
The x..y
syntax is sugar for std::ops::Range { start: x, end: y }
. This type (Range<A>
) is iterable due to the implementation of Iterator
for it, specifically, from that page:
impl<A> Iterator for Range<A>
where A: One + Step,
&'a A: Add<&'a A>,
&'a A::Output == A {
type Item = A;
这是说如果 A
类型实现了 OneRange
可以作为 A
上的迭代器/code> 和 Step
,并且可以通过正确的方式添加.
This is saying that Range<A>
can behave as an iterator over A
s if the type A
implements One
and Step
, and can be added in the right way.
在这种情况下,char
不满足任何一个:char
具有 One
或可添加在语义上是无稽之谈,而且它也没有实现 Step
.
In this case, char
satisfies none of those: it is semantically nonsense for char
to have One
or be addable, and it doesn't implement Step
either.
也就是说,因为 char
没有实现这些特征(因此 Range
不像迭代器那样通过 impl
代码>),应该可以有手动实现:
That said, since char
doesn't implement those traits (and hence Range<char>
doesn't behave like an iterator via that impl
), it should be possible to have a manual impl:
impl Iterator for Range<char> {
type Item = char;
这将允许 for x in 'a'..'z'
工作.
然而,这在语义上可能不是我们想要的:..
范围不包括最后一个元素,这对于字符来说是令人惊讶的,必须编写 'a'..'{'
来获取字母 A 到 Z.已经提出了包含范围语法的建议,例如一个例子是 'a'...'z'
(更多的点 == 更多的元素),我想对于这种类型会有一个 Iterator
实现char
s.
However, this probably isn't semantically what we want: the ..
range doesn't include the last element, which would be suprising for characters, one would have to write 'a'..'{'
to get the letters A through Z. There's been proposals for inclusive-range syntax, e.g. one example is 'a'...'z'
(more dots == more elements), and I would imagine that there would be an Iterator
implementation for this type with char
s.
正如其他人所证明的,对于 ASCII 字符,可以使用字节文字,更一般地,可以将字符转换为 u32
s:
As others have demonstrated, for ASCII characters one can use byte literals, and more generally, one can cast characters to u32
s:
for i in ('à' as u32)..('æ' as u32) + 1 {
let c = std::char::from_u32(i).unwrap();
println!("{}", c);
}
给出:
à
á
â
ã
ä
å
æ
注意.这种方法并不完美,如果范围超过 surrogate 范围,0xD800,它会崩溃-0xDFFF.
NB. this approach isn't perfect, it will crash if the range crosses the surrogate range, 0xD800-0xDFFF.
我刚刚发布了一个 crate,char-iter
,它正确地处理后者并且表现得像人们期望的那样.添加后(通过货物),它可以像这样使用:
I just published a crate, char-iter
, which handles the latter correctly and behaves like one would expect. Once added (via cargo), it can be used like:
extern crate char_iter;
// ...
for c in char_iter::new('a', 'z') {
// ...
}
for c in char_iter::new('à', 'æ') {
// ...
}
这篇关于为什么需要 num::One 来迭代一个范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!