Iterator with `&mut` items [duplicate] - iterator
I am having trouble expressing the lifetime of the return value of an Iterator implementation. How can I compile this code without changing the return value of the iterator? I'd like it to return a vector of references.
It is obvious that I am not using the lifetime parameter correctly but after trying various ways I just gave up, I have no idea what to do with it.
use std::iter::Iterator;
struct PermutationIterator<T> {
vs: Vec<Vec<T>>,
is: Vec<usize>,
}
impl<T> PermutationIterator<T> {
fn new() -> PermutationIterator<T> {
PermutationIterator {
vs: vec![],
is: vec![],
}
}
fn add(&mut self, v: Vec<T>) {
self.vs.push(v);
self.is.push(0);
}
}
impl<T> Iterator for PermutationIterator<T> {
type Item = Vec<&'a T>;
fn next(&mut self) -> Option<Vec<&T>> {
'outer: loop {
for i in 0..self.vs.len() {
if self.is[i] >= self.vs[i].len() {
if i == 0 {
return None; // we are done
}
self.is[i] = 0;
self.is[i - 1] += 1;
continue 'outer;
}
}
let mut result = vec![];
for i in 0..self.vs.len() {
let index = self.is[i];
result.push(self.vs[i].get(index).unwrap());
}
*self.is.last_mut().unwrap() += 1;
return Some(result);
}
}
}
fn main() {
let v1: Vec<_> = (1..3).collect();
let v2: Vec<_> = (3..5).collect();
let v3: Vec<_> = (1..6).collect();
let mut i = PermutationIterator::new();
i.add(v1);
i.add(v2);
i.add(v3);
loop {
match i.next() {
Some(v) => {
println!("{:?}", v);
}
None => {
break;
}
}
}
}
(Playground link)
error[E0261]: use of undeclared lifetime name `'a`
--> src/main.rs:23:22
|
23 | type Item = Vec<&'a T>;
| ^^ undeclared lifetime
As far as I understand, you want want the iterator to return a vector of references into itself, right? Unfortunately, it is not possible in Rust.
This is the trimmed down Iterator trait:
trait Iterator {
type Item;
fn next(&mut self) -> Option<Item>;
}
Note that there is no lifetime connection between &mut self and Option<Item>. This means that next() method can't return references into the iterator itself. You just can't express a lifetime of the returned references. This is basically the reason that you couldn't find a way to specify the correct lifetime - it would've looked like this:
fn next<'a>(&'a mut self) -> Option<Vec<&'a T>>
except that this is not a valid next() method for Iterator trait.
Such iterators (the ones which can return references into themselves) are called streaming iterators. You can find more here, here and here, if you want.
Update. However, you can return a reference to some other structure from your iterator - that's how most of collection iterators work. It could look like this:
pub struct PermutationIterator<'a, T> {
vs: &'a [Vec<T>],
is: Vec<usize>
}
impl<'a, T> Iterator for PermutationIterator<'a, T> {
type Item = Vec<&'a T>;
fn next(&mut self) -> Option<Vec<&'a T>> {
...
}
}
Note how lifetime 'a is now declared on impl block. It is OK to do so (required, in fact) because you need to specify the lifetime parameter on the structure. Then you can use the same 'a both in Item and in next() return type. Again, that's how most of collection iterators work.
#VladimirMatveev's answer is correct in how it explains why your code cannot compile. In a nutshell, it says that an Iterator cannot yield borrowed values from within itself.
However, it can yield borrowed values from something else. This is what is achieved with Vec and Iter: the Vec owns the values, and the the Iter is just a wrapper able to yield references within the Vec.
Here is a design which achieves what you want. The iterator is, like with Vec and Iter, just a wrapper over other containers who actually own the values.
use std::iter::Iterator;
struct PermutationIterator<'a, T: 'a> {
vs : Vec<&'a [T]>,
is : Vec<usize>
}
impl<'a, T> PermutationIterator<'a, T> {
fn new() -> PermutationIterator<'a, T> { ... }
fn add(&mut self, v : &'a [T]) { ... }
}
impl<'a, T> Iterator for PermutationIterator<'a, T> {
type Item = Vec<&'a T>;
fn next(&mut self) -> Option<Vec<&'a T>> { ... }
}
fn main() {
let v1 : Vec<i32> = (1..3).collect();
let v2 : Vec<i32> = (3..5).collect();
let v3 : Vec<i32> = (1..6).collect();
let mut i = PermutationIterator::new();
i.add(&v1);
i.add(&v2);
i.add(&v3);
loop {
match i.next() {
Some(v) => { println!("{:?}", v); }
None => {break;}
}
}
}
(Playground)
Unrelated to your initial problem. If this were just me, I would ensure that all borrowed vectors are taken at once. The idea is to remove the repeated calls to add and to pass directly all borrowed vectors at construction:
use std::iter::{Iterator, repeat};
struct PermutationIterator<'a, T: 'a> {
...
}
impl<'a, T> PermutationIterator<'a, T> {
fn new(vs: Vec<&'a [T]>) -> PermutationIterator<'a, T> {
let n = vs.len();
PermutationIterator {
vs: vs,
is: repeat(0).take(n).collect(),
}
}
}
impl<'a, T> Iterator for PermutationIterator<'a, T> {
...
}
fn main() {
let v1 : Vec<i32> = (1..3).collect();
let v2 : Vec<i32> = (3..5).collect();
let v3 : Vec<i32> = (1..6).collect();
let vall: Vec<&[i32]> = vec![&v1, &v2, &v3];
let mut i = PermutationIterator::new(vall);
}
(Playground)
(EDIT: Changed the iterator design to take a Vec<&'a [T]> rather than a Vec<Vec<&'a T>>. It's easier to take a ref to container than to build a container of refs.)
As mentioned in other answers, this is called a streaming iterator and it requires different guarantees from Rust's Iterator. One crate that provides such functionality is aptly called streaming-iterator and it provides the StreamingIterator trait.
Here is one example of implementing the trait:
extern crate streaming_iterator;
use streaming_iterator::StreamingIterator;
struct Demonstration {
scores: Vec<i32>,
position: usize,
}
// Since `StreamingIterator` requires that we be able to call
// `advance` before `get`, we have to start "before" the first
// element. We assume that there will never be the maximum number of
// entries in the `Vec`, so we use `usize::MAX` as our sentinel value.
impl Demonstration {
fn new() -> Self {
Demonstration {
scores: vec![1, 2, 3],
position: std::usize::MAX,
}
}
fn reset(&mut self) {
self.position = std::usize::MAX;
}
}
impl StreamingIterator for Demonstration {
type Item = i32;
fn advance(&mut self) {
self.position = self.position.wrapping_add(1);
}
fn get(&self) -> Option<&Self::Item> {
self.scores.get(self.position)
}
}
fn main() {
let mut example = Demonstration::new();
loop {
example.advance();
match example.get() {
Some(v) => {
println!("v: {}", v);
}
None => break,
}
}
example.reset();
loop {
example.advance();
match example.get() {
Some(v) => {
println!("v: {}", v);
}
None => break,
}
}
}
Unfortunately, streaming iterators will be limited until generic associated types (GATs) from RFC 1598 are implemented.
I wrote this code not long ago and somehow stumbled on this question here. It does exactly what the question asks: it shows how to implement an iterator that passes its callbacks a reference to itself.
It adds an .iter_map() method to IntoIterator instances. Initially I thought it should be implemented for Iterator itself, but that was a less flexible design decision.
I created a small crate for it and posted my code to GitHub in case you want to experiment with it, you can find it here.
WRT the OP's trouble with defining lifetimes for the items, I didn't run into any such trouble implementing this while relying on the default elided lifetimes.
Here's an example of usage. Note the parameter the callback receives is the iterator itself, the callback is expected to pull the data from it and either pass it along as is or do whatever other operations.
use iter_map::IntoIterMap;
let mut b = true;
let s = "hello world!".chars().peekable().iter_map(|iter| {
if let Some(&ch) = iter.peek() {
if ch == 'o' && b {
b = false;
Some('0')
} else {
b = true;
iter.next()
}
} else { None }
}).collect::<String>();
assert_eq!(&s, "hell0o w0orld!");
Because the IntoIterMap generic trait is implemented for IntoIterator, you can get an "iter map" off anything that supports that interface. For instance, one can be created directly off an array, like so:
use iter_map::*;
fn main()
{
let mut i = 0;
let v = [1, 2, 3, 4, 5, 6].iter_map(move |iter| {
i += 1;
if i % 3 == 0 {
Some(0)
} else {
iter.next().copied()
}
}).collect::<Vec<_>>();
assert_eq!(v, vec![1, 2, 0, 3, 4, 0, 5, 6, 0]);
}
Here's the full code - it was amazing it took such little code to implement, and everything just seemed to work smoothly while putting it together. It gave me a new appreciation for the flexibility of Rust itself and its design decisions.
/// Adds `.iter_map()` method to all IntoIterator classes.
///
impl<F, I, J, R, T> IntoIterMap<F, I, R, T> for J
//
where F: FnMut(&mut I) -> Option<R>,
I: Iterator<Item = T>,
J: IntoIterator<Item = T, IntoIter = I>,
{
/// Returns an iterator that invokes the callback in `.next()`, passing it
/// the original iterator as an argument. The callback can return any
/// arbitrary type within an `Option`.
///
fn iter_map(self, callback: F) -> ParamFromFnIter<F, I>
{
ParamFromFnIter::new(self.into_iter(), callback)
}
}
/// A trait to add the `.iter_map()` method to any existing class.
///
pub trait IntoIterMap<F, I, R, T>
//
where F: FnMut(&mut I) -> Option<R>,
I: Iterator<Item = T>,
{
/// Returns a `ParamFromFnIter` iterator which wraps the iterator it's
/// invoked on.
///
/// # Arguments
/// * `callback` - The callback that gets invoked by `.next()`.
/// This callback is passed the original iterator as its
/// parameter.
///
fn iter_map(self, callback: F) -> ParamFromFnIter<F, I>;
}
/// Implements an iterator that can be created from a callback.
/// does pretty much the same thing as `std::iter::from_fn()` except the
/// callback signature of this class takes a data argument.
pub struct ParamFromFnIter<F, D>
{
callback: F,
data: D,
}
impl<F, D, R> ParamFromFnIter<F, D>
//
where F: FnMut(&mut D) -> Option<R>,
{
/// Creates a new `ParamFromFnIter` iterator instance.
///
/// This provides a flexible and simple way to create new iterators by
/// defining a callback.
/// # Arguments
/// * `data` - Data that will be passed to the callback on each
/// invocation.
/// * `callback` - The callback that gets invoked when `.next()` is invoked
/// on the returned iterator.
///
pub fn new(data: D, callback: F) -> Self
{
ParamFromFnIter { callback, data }
}
}
/// Implements Iterator for ParamFromFnIter.
///
impl<F, D, R> Iterator for ParamFromFnIter<F, D>
//
where F: FnMut(&mut D) -> Option<R>,
{
type Item = R;
/// Iterator method that returns the next item.
/// Invokes the client code provided iterator, passing it `&mut self.data`.
///
fn next(&mut self) -> Option<Self::Item>
{
(self.callback)(&mut self.data)
}
}
Related
How can I automatically implement FromIterator?
I have written a trait that specifies some methods similar to those of Vec: pub trait Buffer { type Item; fn with_capacity(c: usize) -> Self; fn push(&mut self, item: Self::Item); } I would like to implement FromIterator for all types that implement Buffer, as follows: impl<T> iter::FromIterator<T::Item> for T where T: Buffer { fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = T> { let mut iter = iter.into_iter(); let (lower, _) = iter.size_hint(); let ans = Self::with_capacity(lower); while let Some(x) = iter.next() { ans.push(x); } ans } } The compiler won't let me: error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter I think I understand the error message; it is preventing me from writing code that is incompatible with possible future changes to the standard library. The only way around this error appears to be to implement FromIterator separately for every type for which I implement Buffer. This will involve copying out exactly the same code many times. Is there a a way to share the same implementation between all Buffer types?
You can't implement a trait from another crate for an arbitrary type, only for a type from your crate. However, you can move the implementation to a function and reduce amount of duplicated code: fn buffer_from_iter<I, B>(iter: I) -> B where I: IntoIterator<Item = B::Item>, B: Buffer { let mut iter = iter.into_iter(); let (lower, _) = iter.size_hint(); let mut ans = B::with_capacity(lower); while let Some(x) = iter.next() { ans.push(x); } ans } struct S1; impl Buffer for S1 { type Item = i32; fn with_capacity(c: usize) -> Self { unimplemented!() } fn push(&mut self, item: Self::Item) { unimplemented!() } } impl std::iter::FromIterator<<S1 as Buffer>::Item> for S1 { fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = <S1 as Buffer>::Item> { buffer_from_iter(iter) } } This implementation of FromIterator can be wrapped into a macro to further reduce code duplication.
Wrong number of lifetime parameters when using a modified `Chars` iterator
I want to implement the IntoIterator trait for a struct containing a String. The iterator is based on the chars() iterator, is supposed to count the '1' chars and accumulate the result. This is a simplified version of what I got so far: use std::iter::Map; use std::str::Chars; fn main() { let str_struct = StringStruct { system_string: String::from("1101") }; for a in str_struct { println!("{}", a); } } struct StringStruct { system_string: String } impl IntoIterator for StringStruct { type Item = u32; type IntoIter = Map<Chars, Fn(char) -> u32>; fn into_iter(self) -> Self::IntoIter { let count = 0; return self.system_string.chars().map(|c| match c { Some('1') => { count += 1; return Some(count); }, Some(chr) => return Some(count), None => return None }); } } Expected output: 1, 2, 2, 3 This fails with: error[E0107]: wrong number of lifetime parameters: expected 1, found 0 --> src/main.rs:17:25 | 17 | type IntoIter = Map<Chars, Fn(char) -> u32>; | ^^^^^ expected 1 lifetime parameter The chars iterator should have the same lifetime as the StringStruct::system_string, but I have no idea how to express this or if this approach is viable at all.
To answer the question you asked, I'd recommend to impl IntoIterator for &StringStruct (a reference to a StringStruct instead of the struct directly). The code would look like this: impl<'a> IntoIterator for &'a StringStruct { type Item = u32; type IntoIter = Map<Chars<'a>, Fn(char) -> u32>; // ... } However, you will notice many more errors that have a different origin afterwards. The next error that pops up is that Fn(char) -> u32 does not have a constant size at compile time. The problem is that you try to name the type of your closure by writing Fn(char) -> u32. But this is not the type of your closure, but merely a trait which is implemented by the closure. The type of a closure can't be named (sometimes called "Voldemort type"). This means that, right now, you can't specify the type of a Map<_, _> object. This is a known issue; the recently accepted impl Trait-RFC might offer a workaround for cases like this. But right now, it's not possible, sorry. So how to solve it then? You need to create your own type that implements Iterator and use it instead of Map<_, _>. Note that you can still use the Chars iterator. Here is the full solution: struct StringStructIter<'a> { chars: Chars<'a>, count: u32, } impl<'a> Iterator for StringStructIter<'a> { type Item = u32; fn next(&mut self) -> Option<Self::Item> { self.chars.next().map(|c| { if c == '1' { self.count += 1; } self.count }) } } impl<'a> IntoIterator for &'a StringStruct { type Item = u32; type IntoIter = StringStructIter<'a>; fn into_iter(self) -> Self::IntoIter { StringStructIter { chars: self.system_string.chars(), count: 0, } } } fn main() { let str_struct = StringStruct { system_string: String::from("1101") }; for a in &str_struct { println!("{}", a); } } And just a small note: an explicit return when not necessary is considered bad style in Rust. Better stick to rule and write idiomatic code by removing return whenever possible ;-)
How do I write an iterator that returns references to itself?
I am having trouble expressing the lifetime of the return value of an Iterator implementation. How can I compile this code without changing the return value of the iterator? I'd like it to return a vector of references. It is obvious that I am not using the lifetime parameter correctly but after trying various ways I just gave up, I have no idea what to do with it. use std::iter::Iterator; struct PermutationIterator<T> { vs: Vec<Vec<T>>, is: Vec<usize>, } impl<T> PermutationIterator<T> { fn new() -> PermutationIterator<T> { PermutationIterator { vs: vec![], is: vec![], } } fn add(&mut self, v: Vec<T>) { self.vs.push(v); self.is.push(0); } } impl<T> Iterator for PermutationIterator<T> { type Item = Vec<&'a T>; fn next(&mut self) -> Option<Vec<&T>> { 'outer: loop { for i in 0..self.vs.len() { if self.is[i] >= self.vs[i].len() { if i == 0 { return None; // we are done } self.is[i] = 0; self.is[i - 1] += 1; continue 'outer; } } let mut result = vec![]; for i in 0..self.vs.len() { let index = self.is[i]; result.push(self.vs[i].get(index).unwrap()); } *self.is.last_mut().unwrap() += 1; return Some(result); } } } fn main() { let v1: Vec<_> = (1..3).collect(); let v2: Vec<_> = (3..5).collect(); let v3: Vec<_> = (1..6).collect(); let mut i = PermutationIterator::new(); i.add(v1); i.add(v2); i.add(v3); loop { match i.next() { Some(v) => { println!("{:?}", v); } None => { break; } } } } (Playground link) error[E0261]: use of undeclared lifetime name `'a` --> src/main.rs:23:22 | 23 | type Item = Vec<&'a T>; | ^^ undeclared lifetime
As far as I understand, you want want the iterator to return a vector of references into itself, right? Unfortunately, it is not possible in Rust. This is the trimmed down Iterator trait: trait Iterator { type Item; fn next(&mut self) -> Option<Item>; } Note that there is no lifetime connection between &mut self and Option<Item>. This means that next() method can't return references into the iterator itself. You just can't express a lifetime of the returned references. This is basically the reason that you couldn't find a way to specify the correct lifetime - it would've looked like this: fn next<'a>(&'a mut self) -> Option<Vec<&'a T>> except that this is not a valid next() method for Iterator trait. Such iterators (the ones which can return references into themselves) are called streaming iterators. You can find more here, here and here, if you want. Update. However, you can return a reference to some other structure from your iterator - that's how most of collection iterators work. It could look like this: pub struct PermutationIterator<'a, T> { vs: &'a [Vec<T>], is: Vec<usize> } impl<'a, T> Iterator for PermutationIterator<'a, T> { type Item = Vec<&'a T>; fn next(&mut self) -> Option<Vec<&'a T>> { ... } } Note how lifetime 'a is now declared on impl block. It is OK to do so (required, in fact) because you need to specify the lifetime parameter on the structure. Then you can use the same 'a both in Item and in next() return type. Again, that's how most of collection iterators work.
#VladimirMatveev's answer is correct in how it explains why your code cannot compile. In a nutshell, it says that an Iterator cannot yield borrowed values from within itself. However, it can yield borrowed values from something else. This is what is achieved with Vec and Iter: the Vec owns the values, and the the Iter is just a wrapper able to yield references within the Vec. Here is a design which achieves what you want. The iterator is, like with Vec and Iter, just a wrapper over other containers who actually own the values. use std::iter::Iterator; struct PermutationIterator<'a, T: 'a> { vs : Vec<&'a [T]>, is : Vec<usize> } impl<'a, T> PermutationIterator<'a, T> { fn new() -> PermutationIterator<'a, T> { ... } fn add(&mut self, v : &'a [T]) { ... } } impl<'a, T> Iterator for PermutationIterator<'a, T> { type Item = Vec<&'a T>; fn next(&mut self) -> Option<Vec<&'a T>> { ... } } fn main() { let v1 : Vec<i32> = (1..3).collect(); let v2 : Vec<i32> = (3..5).collect(); let v3 : Vec<i32> = (1..6).collect(); let mut i = PermutationIterator::new(); i.add(&v1); i.add(&v2); i.add(&v3); loop { match i.next() { Some(v) => { println!("{:?}", v); } None => {break;} } } } (Playground) Unrelated to your initial problem. If this were just me, I would ensure that all borrowed vectors are taken at once. The idea is to remove the repeated calls to add and to pass directly all borrowed vectors at construction: use std::iter::{Iterator, repeat}; struct PermutationIterator<'a, T: 'a> { ... } impl<'a, T> PermutationIterator<'a, T> { fn new(vs: Vec<&'a [T]>) -> PermutationIterator<'a, T> { let n = vs.len(); PermutationIterator { vs: vs, is: repeat(0).take(n).collect(), } } } impl<'a, T> Iterator for PermutationIterator<'a, T> { ... } fn main() { let v1 : Vec<i32> = (1..3).collect(); let v2 : Vec<i32> = (3..5).collect(); let v3 : Vec<i32> = (1..6).collect(); let vall: Vec<&[i32]> = vec![&v1, &v2, &v3]; let mut i = PermutationIterator::new(vall); } (Playground) (EDIT: Changed the iterator design to take a Vec<&'a [T]> rather than a Vec<Vec<&'a T>>. It's easier to take a ref to container than to build a container of refs.)
As mentioned in other answers, this is called a streaming iterator and it requires different guarantees from Rust's Iterator. One crate that provides such functionality is aptly called streaming-iterator and it provides the StreamingIterator trait. Here is one example of implementing the trait: extern crate streaming_iterator; use streaming_iterator::StreamingIterator; struct Demonstration { scores: Vec<i32>, position: usize, } // Since `StreamingIterator` requires that we be able to call // `advance` before `get`, we have to start "before" the first // element. We assume that there will never be the maximum number of // entries in the `Vec`, so we use `usize::MAX` as our sentinel value. impl Demonstration { fn new() -> Self { Demonstration { scores: vec![1, 2, 3], position: std::usize::MAX, } } fn reset(&mut self) { self.position = std::usize::MAX; } } impl StreamingIterator for Demonstration { type Item = i32; fn advance(&mut self) { self.position = self.position.wrapping_add(1); } fn get(&self) -> Option<&Self::Item> { self.scores.get(self.position) } } fn main() { let mut example = Demonstration::new(); loop { example.advance(); match example.get() { Some(v) => { println!("v: {}", v); } None => break, } } example.reset(); loop { example.advance(); match example.get() { Some(v) => { println!("v: {}", v); } None => break, } } } Unfortunately, streaming iterators will be limited until generic associated types (GATs) from RFC 1598 are implemented.
I wrote this code not long ago and somehow stumbled on this question here. It does exactly what the question asks: it shows how to implement an iterator that passes its callbacks a reference to itself. It adds an .iter_map() method to IntoIterator instances. Initially I thought it should be implemented for Iterator itself, but that was a less flexible design decision. I created a small crate for it and posted my code to GitHub in case you want to experiment with it, you can find it here. WRT the OP's trouble with defining lifetimes for the items, I didn't run into any such trouble implementing this while relying on the default elided lifetimes. Here's an example of usage. Note the parameter the callback receives is the iterator itself, the callback is expected to pull the data from it and either pass it along as is or do whatever other operations. use iter_map::IntoIterMap; let mut b = true; let s = "hello world!".chars().peekable().iter_map(|iter| { if let Some(&ch) = iter.peek() { if ch == 'o' && b { b = false; Some('0') } else { b = true; iter.next() } } else { None } }).collect::<String>(); assert_eq!(&s, "hell0o w0orld!"); Because the IntoIterMap generic trait is implemented for IntoIterator, you can get an "iter map" off anything that supports that interface. For instance, one can be created directly off an array, like so: use iter_map::*; fn main() { let mut i = 0; let v = [1, 2, 3, 4, 5, 6].iter_map(move |iter| { i += 1; if i % 3 == 0 { Some(0) } else { iter.next().copied() } }).collect::<Vec<_>>(); assert_eq!(v, vec![1, 2, 0, 3, 4, 0, 5, 6, 0]); } Here's the full code - it was amazing it took such little code to implement, and everything just seemed to work smoothly while putting it together. It gave me a new appreciation for the flexibility of Rust itself and its design decisions. /// Adds `.iter_map()` method to all IntoIterator classes. /// impl<F, I, J, R, T> IntoIterMap<F, I, R, T> for J // where F: FnMut(&mut I) -> Option<R>, I: Iterator<Item = T>, J: IntoIterator<Item = T, IntoIter = I>, { /// Returns an iterator that invokes the callback in `.next()`, passing it /// the original iterator as an argument. The callback can return any /// arbitrary type within an `Option`. /// fn iter_map(self, callback: F) -> ParamFromFnIter<F, I> { ParamFromFnIter::new(self.into_iter(), callback) } } /// A trait to add the `.iter_map()` method to any existing class. /// pub trait IntoIterMap<F, I, R, T> // where F: FnMut(&mut I) -> Option<R>, I: Iterator<Item = T>, { /// Returns a `ParamFromFnIter` iterator which wraps the iterator it's /// invoked on. /// /// # Arguments /// * `callback` - The callback that gets invoked by `.next()`. /// This callback is passed the original iterator as its /// parameter. /// fn iter_map(self, callback: F) -> ParamFromFnIter<F, I>; } /// Implements an iterator that can be created from a callback. /// does pretty much the same thing as `std::iter::from_fn()` except the /// callback signature of this class takes a data argument. pub struct ParamFromFnIter<F, D> { callback: F, data: D, } impl<F, D, R> ParamFromFnIter<F, D> // where F: FnMut(&mut D) -> Option<R>, { /// Creates a new `ParamFromFnIter` iterator instance. /// /// This provides a flexible and simple way to create new iterators by /// defining a callback. /// # Arguments /// * `data` - Data that will be passed to the callback on each /// invocation. /// * `callback` - The callback that gets invoked when `.next()` is invoked /// on the returned iterator. /// pub fn new(data: D, callback: F) -> Self { ParamFromFnIter { callback, data } } } /// Implements Iterator for ParamFromFnIter. /// impl<F, D, R> Iterator for ParamFromFnIter<F, D> // where F: FnMut(&mut D) -> Option<R>, { type Item = R; /// Iterator method that returns the next item. /// Invokes the client code provided iterator, passing it `&mut self.data`. /// fn next(&mut self) -> Option<Self::Item> { (self.callback)(&mut self.data) } }
How can I add new methods to Iterator?
I want to define a .unique() method on iterators that enables me to iterate without duplicates. use std::collections::HashSet; struct UniqueState<'a> { seen: HashSet<String>, underlying: &'a mut Iterator<Item = String>, } trait Unique { fn unique(&mut self) -> UniqueState; } impl Unique for Iterator<Item = String> { fn unique(&mut self) -> UniqueState { UniqueState { seen: HashSet::new(), underlying: self, } } } impl<'a> Iterator for UniqueState<'a> { type Item = String; fn next(&mut self) -> Option<String> { while let Some(x) = self.underlying.next() { if !self.seen.contains(&x) { self.seen.insert(x.clone()); return Some(x); } } None } } This compiles. However, when I try to use in the same file: fn main() { let foo = vec!["a", "b", "a", "cc", "cc", "d"]; for s in foo.iter().unique() { println!("{}", s); } } I get the following error: error[E0599]: no method named `unique` found for type `std::slice::Iter<'_, &str>` in the current scope --> src/main.rs:37:25 | 37 | for s in foo.iter().unique() { | ^^^^^^ | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `unique`, perhaps you need to implement it: candidate #1: `Unique` What am I doing wrong? How would I extend this arbitrary hashable types?
In your particular case, it's because you have implemented your trait for an iterator of String, but your vector is providing an iterator of &str. Here's a more generic version: use std::collections::HashSet; use std::hash::Hash; struct Unique<I> where I: Iterator, { seen: HashSet<I::Item>, underlying: I, } impl<I> Iterator for Unique<I> where I: Iterator, I::Item: Hash + Eq + Clone, { type Item = I::Item; fn next(&mut self) -> Option<Self::Item> { while let Some(x) = self.underlying.next() { if !self.seen.contains(&x) { self.seen.insert(x.clone()); return Some(x); } } None } } trait UniqueExt: Iterator { fn unique(self) -> Unique<Self> where Self::Item: Hash + Eq + Clone, Self: Sized, { Unique { seen: HashSet::new(), underlying: self, } } } impl<I: Iterator> UniqueExt for I {} fn main() { let foo = vec!["a", "b", "a", "cc", "cc", "d"]; for s in foo.iter().unique() { println!("{}", s); } } Broadly, we create a new extension trait called UniqueExt which has Iterator as a supertrait. When Iterator is a supertrait, we will have access to the associated type Iterator::Item. This trait defines the unique method, which is only valid to call when then iterated item can be: Hashed Compared for total equality Cloned Additionally, it requires that the item implementing Iterator have a known size at compile time. This is done so that the iterator can be consumed by the Unique iterator adapter. The other important part is the blanket implementation of the trait for any type that also implements Iterator: impl<I: Iterator> UniqueExt for I {}
Rust: Create an Iterator out of Default and Succ?
I have the following code in a repo: impl<Id> IdAllocator<Id> where Id : Clone + Default + Add<u32, Id>, { pub fn new() -> IdAllocator<Id> { IdAllocator { next: Default::default() } } // Produce an Id that hasn't been produced yet by this object. pub fn allocate(&mut self) -> Id { let ret = self.next.clone(); self.next = self.next + 1; ret } } But it seems a little clumsy, especially since the Add instance is only used as a succ function (generating the next value in sequence). Is there some Succ class I can use? And if so, is there already some Iterator construction somewhere in the standard library that already does this Default+Succ pattern? Thanks!
No, unfortunately, there is no Succ-like thing in the standard library. The closest thing you can find is range() family of iterators, however, it uses Add and One numeric traits to generate items. You can do it this way (the idea is basically the same as yours, but this version is slightly more generic due to One trait usage): use std::num::One; use std::default::Default; struct IdAllocator<T> { current: T } impl<T: Default> IdAllocator<T> { #[inline] pub fn new() -> IdAllocator<T> { IdAllocator { current: Default::default() } } } impl<T: Add<T, T>+One+Clone> Iterator<T> for IdAllocator<T> { fn next(&mut self) -> Option<T> { let next = self.current + One::one(); self.current = next.clone(); Some(next) } } fn main() { let a = IdAllocator::<uint>::new(); for i in a.take(10) { println!("{}", i); } } (try it here)