2 stable releases
new 1.0.1 | Nov 25, 2024 |
---|
#227 in Rust patterns
13KB
83 lines
iterate-trait
Why does this project exist?
This project asks the question: what if we used IntoIterator
everywhere
instead of Iterator
? This becomes relevant for generator blocks, which
themselves may contain !Send
items, but that doesn't mean that the type
returned by gen {}
needs to be !Send
too. This crate follows Swift's
example, making it so all operations happen on a base builder type - which
has one final operation that converts it into an actual iterable.
The other reason is that in bounds we already always use IntoIterator
. For
example the collect
method takes A: IntoIterator
, not A: Iterator
. In
function bounds there is rarely a reason to use Iterator
directly; typically the
only reason we don't is because it's more effort to type.
Example of Iterator
's limitations
Here's a practical case people are bound to hit when writing generator
blocks, which can't be fixed unless generator returns IntoIterator
:
// A gen block that holds some `!Send` type across a yield point
let iter = gen {
let items = my_data.lock(); // ← `MutexGuard: !Send`
for item in items {
yield item;
}
};
// ## Option 1
let iter = gen { ... }; // 1. Desugars to `impl Iterator + !Send`
thread::spawn(move || { // 2. ❌ Can't move `!Send` type across threads
for item in iter { ... }
}).unwrap();
// ## Option 2
let iter = gen { ... }; // 1. Desugars to `impl IntoIterator + Send`
thread::spawn(move || { // 2. ✅ Move `Send` type across threads
for item in iter { ... } // 3. Obtain `impl Iterator + !Send`
}).unwrap();
Why did you choose these names?
This crate essentially reframes IntoIterator
into the main interface for
iteration. However the name IntoIterator
suggests it is a mere supplement
to some other Iterator
trait. Iterator
also has another quirk: it's a
trait that's named after a noun, rather than a verb. Think of Read
,
Write
, Send
- these are all verbs.
The closest prior art for this in the stdlib I could find was the Hash
/
Hasher
pair. The main trait Hash
is the subject of the hashing, with
Hasher
containing all the hash state. This makes Hasher
very similar to
Iterator
, and hints the better name for IntoIterator
might in fact be Iterate
.
This just leaves us with what to do about FromIterator
, which currently
exists as a dual to IntoIterator
. But interestingly it also exists as a
dual to Extend
,
where rather than creating a new container it can be used to extend an
existing collection. This is also used in the unstable collect_into
method.
It's for this reason that we've renamed FromIterator
to Collect
. All
together this changes the names to:
IntoIterator
→Iterate
Iterator
→Iterator
FromIterator
→Collect
Installation
$ cargo add iterate-trait
Safety
This crate uses #![deny(unsafe_code)]
to ensure everything is implemented in
100% Safe Rust.
Contributing
Want to join us? Check out our "Contributing" guide and take a look at some of these issues:
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.