Rust 为什么在一个范围内迭代需要num::One?
为什么以下具有char范围的for循环无法编译Rust 为什么在一个范围内迭代需要num::One?,rust,Rust,为什么以下具有char范围的for循环无法编译 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
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
来迭代一个范围呢?好吧,你需要Step
来表示这个结构可以在两个方向上跨接
/// Objects that can be stepped over in both directions.
///
/// The `steps_between` function provides a way to efficiently compare
/// two `Step` objects.
pub trait Step: PartialOrd
另一方面,一个
用于从可变迭代器中检索值,同时递增该值:
#[inline]
fn next(&mut self) -> Option<A> {
if self.start < self.end {
let mut n = &self.start + &A::one();
mem::swap(&mut n, &mut self.start);
Some(n)
} else {
None
}
}
注意:该范围是独占的,因此('a'..'z')实际上是('a','b','y')。或者用数学符号[a,z)
;)
这就是为什么我添加了b'z'+1
,而不是b'z'
注意:u8是有效的,只是因为字符是ASCII。对于
x..y
语法是sugar。这种类型(范围不满足这些条件:char
具有One
或可添加在语义上是无意义的,并且它也不实现步骤
这就是说,由于char
没有实现这些特性(因此Range
通过impl
的行为不像迭代器),因此应该有一个手动impl:
impl Iterator for Range<char> {
type Item = char;
其中:
à
á
â
ã
ä
å
æ
注意:这种方法并不完美,如果范围超过范围0xD800-0xDFFF,它将崩溃
我刚刚发布了一个板条箱,它可以正确地处理后者,并表现出人们所期望的行为。一旦添加(通过货物),它可以像这样使用:
extern crate char_iter;
// ...
for c in char_iter::new('a', 'z') {
// ...
}
for c in char_iter::new('à', 'æ') {
// ...
}
+1作为您的解释,但解决方案看起来相当笨拙。Unicode字符不是按代码点排序的吗?rust是否有一些函数可用于获取当前Unicode字符后的下一个Unicode字符?对于您不拥有的类型,您无法实现您不拥有的特征。您必须至少拥有其中一个。@Shepmaster哦,对了,我是忘记了一致性规则。你可以编写一个包装器UnicodeRange((1..2))
,或者在返回迭代器('a'..'z').unicode\u iter()
的范围内实现一个trait。这看起来很愚蠢,但可能会奏效。
à
á
â
ã
ä
å
æ
extern crate char_iter;
// ...
for c in char_iter::new('a', 'z') {
// ...
}
for c in char_iter::new('à', 'æ') {
// ...
}