Unten finden Sie eine Übersetzung eines Teils der Artikelserie des Rust Crash Course von Michael Snoiman, die sich auf Iteratoren konzentriert. Das Material schien mir in Bezug auf die Zugänglichkeit erfolgreich zu sein, daher beschloss ich, die Übersetzung, die ich für mich selbst angefertigt hatte, zu veröffentlichen. Hoffe das ist nützlich für jemanden. Wenn dieses Material interessant ist, werde ich einige weitere Übersetzungen aus dieser Reihe veröffentlichen.
Ich habe auch versucht, so nah wie möglich am Stil des Autors zu übersetzen, aber ein paar Interdomes und Ausrufe reduziert, die für die Bedeutung nicht sehr wichtig sind.
Mehr Iteratoren!
Ich selbst habe festgestellt, dass der einfachste Weg, die Funktionsweise von Iteratoren zu verstehen, darin besteht, einige davon selbst zu schreiben. Hier fangen wir also an.
Lassen Sie uns eine compilergesteuerte Programmierung durchführen. Wir haben zuvor besprochen, dass es ein Merkmal gibt Iterator
. Ich wette, wir müssen einen neuen Datentyp erstellen und eine Implementierung für dieses Merkmal bereitstellen. Beginnen wir mit etwas Einfachem, einem Iterator, der überhaupt keine Werte erzeugt.
struct Empty;
fn main() {
for i in Empty {
panic!("Wait, this shouldn't happen!");
}
println!("All done!");
}
Panic ( panic!()
) ist eine Möglichkeit, den aktuellen Thread zu beenden, wenn eine unmögliche Situation auftritt. Dies ähnelt Laufzeitausnahmen in anderen Sprachen, kann jedoch nicht wiederhergestellt werden. Es sollte also nur für solche Situationen verwendet werden.
Lassen Sie uns dies kompilieren und eine hilfreiche Fehlermeldung erhalten:
error[E0277]: `Empty` is not an iterator --> src/main.rs:5:14 | 5 | for i in Empty { | ^^^^^ `Empty` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `Empty` = note: required by `std::iter::IntoIterator::into_iter`
:
impl Iterator for Empty {
}
:
error[E0046]: not all trait items implemented, missing: `Item`, `next` --> src/main.rs:4:1 | 4 | impl Iterator for Empty { | ^^^^^^^^^^^^^^^^^^^^^^^ missing `Item`, `next` in implementation | = help: implement the missing item: `type Item = Type;` = help: implement the missing item: `fn next(&mut self) -> std::option::Option<<Self as std::iter::Iterator>::Item> { todo!() }`
, : Item
next()
, , . type Item
? , (associated type). , . , . u32
:
struct Empty;
impl Iterator for Empty {
type Item = u32;
}
- next
. :
fn(&mut Self) -> std::option::Option<<Self as std::iter::Iterator>::Item>
. — &mut Self
. , &mut self
. ? , &mut self
— self: &mut Self
.
fn(&mut self) -> std::option::Option<<Self as std::iter::Iterator>::Item>
Option
Iterator
, (namespace):
fn(&mut self) -> Option<<Self as Iterator>::Item>
Self as Iterator
: " Iterator
". , , — ::Item
. , , " Item
, Iterator
". , , .
, ? :
struct Empty;
impl Iterator for Empty {
type Item = u32;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unimplemented!()
}
}
unimplemented!()
— , panic!()
. , . () unimplemented!()
.
, as Iterator
, :
fn next(&mut self) -> Option<Self::Item>
, Self::Item
u32
. — , , Item
, . .
. Option
, (enum
) : None
Some
. " ", — " -". , , None
, :
struct Empty;
impl Iterator for Empty {
type item = u32;
fn next(&mut self) -> Option<u32> {
None
}
}
Iterator
.
, 42
. main
.
fn main() {
// only take 10 to avoid looping forever
for i in TheAnswer.take(10) {
println!("The answer to life, the universe, and everything is {}", i);
}
println!("All done!");
}
struct TheAnswer;
impl Iterator for TheAnswer {
type Item = u32;
fn next(&mut self) -> Option<u32> {
Some(42)
}
}
next
self
. ! , 1 10. ( , , , ).
struct OneToTen(u32);
fn one_to_ten() -> OneToTen {
OneToTen(1)
}
impl Iterator for OneToTen {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.0 > 10 {
None
} else {
let res = Some(self.0);
self.0 += 1;
res
}
}
}
fn main() {
for i in one_to_ten() {
println!("{}", i);
}
}
, .
Beginnen wir mit der einfachsten Lösung
struct Fibs {
x: u32,
y: u32,
}
fn fibs() -> Fibs {
Fibs {
x: 0,
y: 1,
}
}
impl Iterator for Fibs {
type Item = u32;
fn next(&mut self) -> Option<u32> {
let orig_x = self.x;
let orig_y = self.y;
self.x = orig_y;
self.y = orig_x + orig_y;
Some(orig_x)
}
}
fn main() {
for i in fibs().take(10) {
println!("{}", i);
}
}
Wenn Sie jedoch ersetzen take(10)
mit take(47)
, dann wird das Programm Ausgabe wie folgt aussehen:
701408733 1134903170 thread 'main' panicked at 'attempt to add with overflow', foo.rs:21:18 note: Run with `RUST_BACKTRACE=1` for a backtrace.
u64
, . :
fn next(&mut self) -> Option<u32> {
let orig_x = self.x;
let orig_y = self.y;
match orig_x.checked_add(orig_y) {
// overflow
None => None,
// no overflow
Some(new_y) => {
self.x = orig_y;
self.y = new_y;
Some(orig_x)
}
}
}
, .
, . , enum
:
fn next(&mut self) -> Option<u32> {
use Fibs::*;
match *self {
Done => None,
OneLeft(x) => {
*self = Done;
Some(x)
}
Running(orig_x, orig_y) => {
*self = match orig_x.checked_add(orig_y) {
// overflow
None => OneLeft(orig_y),
Some(new_y) => Running(orig_y, new_y),
};
Some(orig_x)
}
}
}
:
enum FibonacciIterState {
FirstItem,
SecondItem,
NthItem(u64, u64),
Overflowed,
}
struct FibonacciIterator {
state: FibonacciIterState,
}
impl FibonacciIterator {
fn new() -> FibonacciIterator {
FibonacciIterator{ state: FibonacciIterState::FirstItem }
}
}
impl Iterator for FibonacciIterator {
type Item = u64;
fn next(&mut self) -> Option<<FibonacciIterator as Iterator>::Item> {
match self.state {
FibonacciIterState::FirstItem => {
self.state = FibonacciIterState::SecondItem;
Some(0)
},
FibonacciIterState::SecondItem => {
self.state = FibonacciIterState::NthItem(0, 1);
Some(1)
},
FibonacciIterState::NthItem(prev, last) => {
if let Some(next) = prev.checked_add(last) {
self.state = FibonacciIterState::NthItem(last, next);
Some(next)
} else {
self.state = FibonacciIterState::Overflowed;
None
}
},
FibonacciIterState::Overflowed => {
None
}
}
}
}
, . (Doubler), , . , , , :
struct Doubler<I> {
iter: I,
}
main
, , :
fn main() {
let orig_iter = 1..11; // 1 10
let doubled_iter = Doubler {
iter: orig_iter,
};
for i in doubled_iter {
println!("{}", i);
}
}
, - Iterator
. :
impl Iterator for Doubler {
}
:
error[E0107]: wrong number of type arguments: expected 1, found 0 --> src/main.rs:6:19 | 6 | impl Iterator for Doubler { | ^^^^^^^ expected 1 type argument
, . Doubler
, . :
impl Iterator for Doubler<I> {
}
. , . (: , ).
:
error[E0412]: cannot find type `I` in this scope --> foo.rs:5:27 | 5 | impl Iterator for Doubler<I> { | ^ not found in this scope
? , , . :
impl<I> Iterator for Doubler<I> {
}
( ), , .
, type Item
next
. u32
:
type Item = u32;
fn next(&mut self) -> Option<u32> {
unimplemented!()
}
, unimplemented!
. , !
, . ( : , map
Option
, ):
fn next(&mut self) -> Option<u32> {
match self.iter.next() {
None => None,
Some(x) => Some(x * 2),
}
}
, :
error[E0599]: no method named `next` found for type parameter `I` in the current scope --> src/main.rs:9:25 | 9 | match self.iter.next() { | ^^^^ method not found in `I` | = help: items from traits can only be used if the type parameter is bounded by the trait help: the following traits define an item `next`, perhaps you need to restrict type parameter `I` with one of them: | 6 | impl<I: std::iter::Iterator> Iterator for Doubler<I> { | ^^^^^^^^^^^^^^^^^^^^^^ 6 | impl<I: std::str::pattern::Searcher> Iterator for Doubler<I> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
, next
Iterator
. . , . , ! , I
Iterator
.
impl<I: Iterator> Iterator for Doubler<I>
, : I
Iterator
. , , :
error[E0369]: cannot multiply `{integer}` to `<I as std::iter::Iterator>::Item` --> src/main.rs:11:31 | 11 | Some(x) => Some(x * 2), | - ^ - {integer} | | | <I as std::iter::Iterator>::Item | = note: the trait `std::ops::Mul` is not implemented for `<I as std::iter::Iterator>::Item`
. I
— - Iterator
, . , x
, x * 2
I
Item
. , , , !
, u32
, , Item
u32
? !
impl<I: Iterator<Item=u32>> Iterator for Doubler<I>
, !
: where
, impl
. where
:
impl<I> Iterator for Doubler<I>
where I: Iterator<Item=u32>
. (consistency) , where
. . .
u32
, u32
. , main
:
let orig_iter = 1..11u64;
:
error[E0271]: type mismatch resolving `<std::ops::Range<u64> as std::iter::Iterator>::Item == u32` --> src/main.rs:24:14 | 24 | for i in doubled_iter { | ^^^^^^^^^^^^ expected `u64`, found `u32` | = note: required because of the requirements on the impl of `std::iter::Iterator` for `Doubler<std::ops::Range<u64>>`
, . ! u32
. :
impl<I> Iterator for Doubler<I>
where I: iterator
{
type Item = ???;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => None,
Some(x) => Some(x * 2),
}
}
}
Option<u32>
Option<Self::Item>
<Item = u32>
I: Iterator
. type Item=
? , , Item
. !
type Item = I::Item;
! , , I::Item
. , Mul
, . :
where
I: Iterator,
I::Item: std::ops::Mul,
:
error[E0308]: mismatched types --> foo.rs:14:29 | 14 | Some(x) => Some(x * From::from(2u8)), | ^^^^^^^^^^^^^^^^^^^ expected std::iter::Iterator::Item, found std::ops::Mul::Output | = note: expected type `<I as std::iter::Iterator>::Item` found type `<<I as std::iter::Iterator>::Item as std::ops::Mul>::Output`
, Mul
. . , (Force
), (Mass
) (Acceleration
), Mul
, (Mass
) (Acceleration
), (Force
).
, . , , item
:
impl<I> Iterator for Doubler<I>
whereI: Iterator,
I::Item: std::ops::Mul<Output=I::Item>,
:
error[E0308]: mismatched types --> foo.rs:14:33 | 14 | Some(x) => Some(x * 2), | ^ expected associated type, found integral variable | = note: expected type `<I as std::iter::Iterator>::Item` found type `{integer}`
. 2
, - . , Item
- . , , ( — , ). , , (upcast) u8
From
, ( ).
impl<I> Iterator for Doubler<I>
where
I: iterator,
I::Item: std::ops::Mul<Output=I::Item> + From<u8>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => None,
Some(x) => Some(x * From::from(2u8)),
}
}
}
, - !
— x + x
x * 2
. . : , , .
impl<I> Iterator for Doubler<I>
where
I: Iterator,
I::Item: std::ops::Add<Output=I::Item> + Copy,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => None,
Some(x) => Some(x + x),
}
}
}
. , , . , . Doubler
, . Empty
, . .
, , . , . , , , .
Doubler
, , . :
fn main() {
for i in (1..11).map(|x| x * 2) {
println!("{}", i);
}
}
Iterator
, . :
fn main() {
for i in (1..11).skip(3).map(|x| x + 1).filter(|x| x % 2 == 0) {
println!("{}", i);
}
}
C/C++, :
- : ,
:
fn main() {
let my_vec: Vec<u32> = (1..11).collect();
println!("{:?}", my_vec);
}
, collect
.
fold
1 10. : sum
.
fold
: . :
fn main() {
let res = (1..11).fold(0, |x, y| x + y);
println!("{}", res);
}
. , Mul
*
? Add
:
fn main() {
let res = (1..11).fold(0, std::ops::Add::add);
println!("{}", res);
}
: , . , From
u8
:
fn sum<I>(iter: I) -> I::Item
where
I: Iterator,
I::Item: std::ops::Add<Output=I::Item> + From<u8>,
{
iter.fold(From::from(0u8), std::ops::Add::add)
}