Movatterモバイル変換


[0]ホーム

URL:


Module iter

std

Moduleiter 

1.0.0 ·Source
Expand description

Composable external iteration.

If you’ve found yourself with a collection of some kind, and needed toperform an operation on the elements of said collection, you’ll quickly runinto ‘iterators’. Iterators are heavily used in idiomatic Rust code, soit’s worth becoming familiar with them.

Before explaining more, let’s talk about how this module is structured:

§Organization

This module is largely organized by type:

  • Traits are the core portion: these traits define what kind of iteratorsexist and what you can do with them. The methods of these traits are worthputting some extra study time into.
  • Functions provide some helpful ways to create some basic iterators.
  • Structs are often the return types of the various methods on thismodule’s traits. You’ll usually want to look at the method that createsthestruct, rather than thestruct itself. For more detail about why,see ‘Implementing Iterator’.

That’s it! Let’s dig into iterators.

§Iterator

The heart and soul of this module is theIterator trait. The core ofIterator looks like this:

traitIterator {typeItem;fnnext(&mutself) ->Option<Self::Item>;}

An iterator has a method,next, which when called, returns anOption<Item>. Callingnext will returnSome(Item) as long as thereare elements, and once they’ve all been exhausted, will returnNone toindicate that iteration is finished. Individual iterators may choose toresume iteration, and so callingnext again may or may not eventuallystart returningSome(Item) again at some point (for example, seeTryIter).

Iterator’s full definition includes a number of other methods as well,but they are default methods, built on top ofnext, and so you getthem for free.

Iterators are also composable, and it’s common to chain them together to domore complex forms of processing. See theAdapters sectionbelow for more details.

§The three forms of iteration

There are three common methods which can create iterators from a collection:

  • iter(), which iterates over&T.
  • iter_mut(), which iterates over&mut T.
  • into_iter(), which iterates overT.

Various things in the standard library may implement one or more of thethree, where appropriate.

§Implementing Iterator

Creating an iterator of your own involves two steps: creating astruct tohold the iterator’s state, and then implementingIterator for thatstruct.This is why there are so manystructs in this module: there is one foreach iterator and iterator adapter.

Let’s make an iterator namedCounter which counts from1 to5:

// First, the struct:/// An iterator which counts from one to fivestructCounter {    count: usize,}// we want our count to start at one, so let's add a new() method to help.// This isn't strictly necessary, but is convenient. Note that we start// `count` at zero, we'll see why in `next()`'s implementation below.implCounter {fnnew() -> Counter {        Counter { count:0}    }}// Then, we implement `Iterator` for our `Counter`:implIteratorforCounter {// we will be counting with usizetypeItem = usize;// next() is the only required methodfnnext(&mutself) ->Option<Self::Item> {// Increment our count. This is why we started at zero.self.count +=1;// Check to see if we've finished counting or not.ifself.count <6{Some(self.count)        }else{None}    }}// And now we can use it!letmutcounter = Counter::new();assert_eq!(counter.next(),Some(1));assert_eq!(counter.next(),Some(2));assert_eq!(counter.next(),Some(3));assert_eq!(counter.next(),Some(4));assert_eq!(counter.next(),Some(5));assert_eq!(counter.next(),None);

Callingnext this way gets repetitive. Rust has a construct which cancallnext on your iterator, until it reachesNone. Let’s go over thatnext.

Also note thatIterator provides a default implementation of methods such asnth andfoldwhich callnext internally. However, it is also possible to write a custom implementation ofmethods likenth andfold if an iterator can compute them more efficiently without callingnext.

§for loops andIntoIterator

Rust’sfor loop syntax is actually sugar for iterators. Here’s a basicexample offor:

letvalues =vec![1,2,3,4,5];forxinvalues {println!("{x}");}

This will print the numbers one through five, each on their own line. Butyou’ll notice something here: we never called anything on our vector toproduce an iterator. What gives?

There’s a trait in the standard library for converting something into aniterator:IntoIterator. This trait has one method,into_iter,which converts the thing implementingIntoIterator into an iterator.Let’s take a look at thatfor loop again, and what the compiler convertsit into:

letvalues =vec![1,2,3,4,5];forxinvalues {println!("{x}");}

Rust de-sugars this into:

letvalues =vec![1,2,3,4,5];{letresult =matchIntoIterator::into_iter(values) {mutiter =>loop{letnext;matchiter.next() {Some(val) => next = val,None=>break,            };letx = next;let() = {println!("{x}"); };        },    };    result}

First, we callinto_iter() on the value. Then, we match on the iteratorthat returns, callingnext over and over until we see aNone. Atthat point, webreak out of the loop, and we’re done iterating.

There’s one more subtle bit here: the standard library contains aninteresting implementation ofIntoIterator:

impl<I: Iterator> IntoIteratorforI

In other words, allIterators implementIntoIterator, by justreturning themselves. This means two things:

  1. If you’re writing anIterator, you can use it with afor loop.
  2. If you’re creating a collection, implementingIntoIterator for itwill allow your collection to be used with thefor loop.

§Iterating by reference

Sinceinto_iter() takesself by value, using afor loop to iterateover a collection consumes that collection. Often, you may want to iterateover a collection without consuming it. Many collections offer methods thatprovide iterators over references, conventionally callediter() anditer_mut() respectively:

letmutvalues =vec![41];forxinvalues.iter_mut() {*x +=1;}forxinvalues.iter() {assert_eq!(*x,42);}assert_eq!(values.len(),1);// `values` is still owned by this function.

If a collection typeC providesiter(), it usually also implementsIntoIterator for&C, with an implementation that just callsiter().Likewise, a collectionC that providesiter_mut() generally implementsIntoIterator for&mut C by delegating toiter_mut(). This enables aconvenient shorthand:

letmutvalues =vec![41];forxin&mutvalues {//   ^ same as `values.iter_mut()`*x +=1;}forxin&values {//   ^ same as `values.iter()`assert_eq!(*x,42);}assert_eq!(values.len(),1);

While many collections offeriter(), not all offeriter_mut(). Forexample, mutating the keys of aHashSet<T> could put the collectioninto an inconsistent state if the key hashes change, so this collectiononly offersiter().

§Adapters

Functions which take anIterator and return anotherIterator areoften called ‘iterator adapters’, as they’re a form of the ‘adapterpattern’.

Common iterator adapters includemap,take, andfilter.For more, see their documentation.

If an iterator adapter panics, the iterator will be in an unspecified (butmemory safe) state. This state is also not guaranteed to stay the sameacross versions of Rust, so you should avoid relying on the exact valuesreturned by an iterator which panicked.

§Laziness

Iterators (and iteratoradapters) arelazy. This means thatjust creating an iterator doesn’tdo a whole lot. Nothing really happensuntil you callnext. This is sometimes a source of confusion whencreating an iterator solely for its side effects. For example, themapmethod calls a closure on each element it iterates over:

letv =vec![1,2,3,4,5];v.iter().map(|x|println!("{x}"));

This will not print any values, as we only created an iterator, rather thanusing it. The compiler will warn us about this kind of behavior:

warning: unused result that must be used: iterators are lazy anddo nothing unless consumed

The idiomatic way to write amap for its side effects is to use afor loop or call thefor_each method:

letv =vec![1,2,3,4,5];v.iter().for_each(|x|println!("{x}"));// orforxin&v {println!("{x}");}

Another common way to evaluate an iterator is to use thecollectmethod to produce a new collection.

§Infinity

Iterators do not have to be finite. As an example, an open-ended range isan infinite iterator:

letnumbers =0..;

It is common to use thetake iterator adapter to turn an infiniteiterator into a finite one:

letnumbers =0..;letfive_numbers = numbers.take(5);fornumberinfive_numbers {println!("{number}");}

This will print the numbers0 through4, each on their own line.

Bear in mind that methods on infinite iterators, even those for which aresult can be determined mathematically in finite time, might not terminate.Specifically, methods such asmin, which in the general case requiretraversing every element in the iterator, are likely not to returnsuccessfully for any infinite iterators.

letones = std::iter::repeat(1);letleast = ones.min().unwrap();// Oh no! An infinite loop!// `ones.min()` causes an infinite loop, so we won't reach this point!println!("The smallest number one is {least}.");

Macros§

iterExperimental
Creates a new closure that returns an iterator where each iteration steps the givengenerator to the nextyield statement.

Structs§

Chain
An iterator that links two iterators together, in a chain.
Cloned
An iterator that clones the elements of an underlying iterator.
Copied
An iterator that copies the elements of an underlying iterator.
Cycle
An iterator that repeats endlessly.
Empty
An iterator that yields nothing.
Enumerate
An iterator that yields the current count and the element during iteration.
Filter
An iterator that filters the elements ofiter withpredicate.
FilterMap
An iterator that usesf to both filter and map elements fromiter.
FlatMap
An iterator that maps each element to an iterator, and yields the elementsof the produced iterators.
Flatten
An iterator that flattens one level of nesting in an iterator of thingsthat can be turned into iterators.
FromFn
An iterator where each iteration calls the provided closureF: FnMut() -> Option<T>.
Fuse
An iterator that yieldsNone forever after the underlying iteratoryieldsNone once.
Inspect
An iterator that calls a function with a reference to each element beforeyielding it.
Map
An iterator that maps the values ofiter withf.
MapWhile
An iterator that only accepts elements whilepredicate returnsSome(_).
Once
An iterator that yields an element exactly once.
OnceWith
An iterator that yields a single element of typeA byapplying the provided closureF: FnOnce() -> A.
Peekable
An iterator with apeek() that returns an optional reference to the nextelement.
Repeat
An iterator that repeats an element endlessly.
RepeatN
An iterator that repeats an element an exact number of times.
RepeatWith
An iterator that repeats elements of typeA endlessly byapplying the provided closureF: FnMut() -> A.
Rev
A double-ended iterator with the direction inverted.
Scan
An iterator to maintain state while iterating another iterator.
Skip
An iterator that skips overn elements ofiter.
SkipWhile
An iterator that rejects elements whilepredicate returnstrue.
StepBy
An iterator for stepping iterators by a custom amount.
Successors
An iterator which, starting from an initial item,computes each successive item from the preceding one.
Take
An iterator that only iterates over the firstn iterations ofiter.
TakeWhile
An iterator that only accepts elements whilepredicate returnstrue.
Zip
An iterator that iterates two other iterators simultaneously.
ArrayChunksExperimental
An iterator overN elements of the iterator at a time.
ByRefSizedExperimental
LikeIterator::by_ref, but requiringSized so it can forward generics.
FromCoroutineExperimental
An iterator over the values yielded by an underlying coroutine.
IntersperseExperimental
An iterator adapter that places a separator between all elements.
IntersperseWithExperimental
An iterator adapter that places a separator between all elements.
MapWindowsExperimental
An iterator over the mapped windows of another iterator.

Traits§

DoubleEndedIterator
An iterator able to yield elements from both ends.
ExactSizeIterator
An iterator that knows its exact length.
Extend
Extend a collection with the contents of an iterator.
FromIterator
Conversion from anIterator.
FusedIterator
An iterator that always continues to yieldNone when exhausted.
IntoIterator
Conversion into anIterator.
Iterator
A trait for dealing with iterators.
Product
Trait to represent types that can be created by multiplying elements of aniterator.
Sum
Trait to represent types that can be created by summing up an iterator.
StepExperimental
Objects that have a notion ofsuccessor andpredecessor operations.
TrustedLenExperimental
An iterator that reports an accurate length using size_hint.
TrustedStepExperimental
A type that upholds all invariants ofStep.

Functions§

chain
Converts the arguments to iterators and links them together, in a chain.
empty
Creates an iterator that yields nothing.
from_fn
Creates an iterator with the provided closureF: FnMut() -> Option<T> as itsnext method.
once
Creates an iterator that yields an element exactly once.
once_with
Creates an iterator that lazily generates a value exactly once by invokingthe provided closure.
repeat
Creates a new iterator that endlessly repeats a single element.
repeat_n
Creates a new iterator that repeats a single element a given number of times.
repeat_with
Creates a new iterator that repeats elements of typeA endlessly byapplying the provided closure, the repeater,F: FnMut() -> A.
successors
Creates an iterator which, starting from an initial item,computes each successive item from the preceding one.
zip
Converts the arguments to iterators and zips them.
from_coroutineExperimental
Creates a new iterator where each iteration calls the provided coroutine.

[8]ページ先頭

©2009-2026 Movatter.jp