- Feature Name: iter_from_closure
- Start Date: 2017-09-03
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)
Summary
Add a function iter_from_closure
for quickly transforming a mutable closure of the right form into an Iterator
.
In other words, the semantics are:
fn iter_from_closure<Item, F>(closure: F) -> impl Iterator<Item = Item>
where F: FnMut() -> Option<Item>
Motivation
Sometimes, you have some state, and from that, you need to create an Iterator
, but only once - and never for reuse.
In such circumstances, it is not ergonomic to create a new struct just to hold the relevant state and then impl Iterator
for that struct and then instantiate the struct.
A more ergonomic solution is to simply take any state you already have, capture it in an FnMut() -> Option<Item>
and then let that closure implement Iterator<Item = Item>
. Unfortunately, it is not possible for FnMut() -> Option<Item>
to directly implement Iterator<Item = Item>
.
Detailed design
Create a function iter_from_closure
which returns an object implementing Iterator<Item = Item>
:
// [bikeshed] iter_from_closure
fn iter_from_closure<Item, F>(closure: F) -> MutFn<Item, F>
where
F: FnMut() -> Option<Item>
{
MutFn::new(closure)
}
where:
// [bikeshed] MutFn
struct MutFn<Item, F>
where
F: FnMut() -> Option<Item>
{
closure: F
}
impl<Item, F> MutFn<Item, F>
where
F: FnMut() -> Option<Item>
{
fn new(closure: F) -> Self {
MutFn {
closure
}
}
}
impl<Item, F> Iterator for MutFn<Item, F>
where
F: FnMut() -> Option<Item>
{
type Item = Item;
fn next(&mut self) -> Option<Self::Item> {
(self.closure)()
}
}
The function iter_from_closure
can then be used as in:
fn main() {
let mut count = 10;
let iter = iter_from_closure(|| {
let c = count;
count = c - 1;
if c > 0 { Some(c) } else { None }
});
println!("{:?}", iter.collect::<Vec<_>>());
}
The function MutFn::new
is not meant to be stabilized at this time. Instead, the public API is iter_from_closure
.
How We Teach This
Documentation on iter_from_closure
and possibly MutFn
should be enough.
Drawbacks
This could be done in an external crate - it could be considered bloat in core
.
Alternatives
- Implement this in an external crate.
Unresolved questions
- Should
impl Iterator<Item = Item>
be used instead? Currently,conservative_impl_trait
will take much longer to stabilize, so williter_from_closure
take as long to stabilize? - Is this needed given the work on generators / co-routines?