I have a struct that gives numbers by method next from trait Iterator:
struct Numbers{
number: usize,
count: usize
}
impl Iterator for Numbers {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
self.count -= 1;
return Some(self.number);
}
return None;
}
}
fn main(){
let numbers = Numbers{
number: 777,
count: 10
};
for n in numbers {
println!{"{:?}", n};
}
}
It's work properly with usize type.
But same code with Box type gives a compilation error:
struct Numbers{
number: Box<usize>,
count: usize
}
impl Iterator for Numbers {
type Item = Box<usize>;
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
self.count -= 1;
return Some(self.number);
}
return None;
}
}
fn main(){
let numbers = Numbers{
number: Box::new(777),
count: 10
};
for n in numbers {
println!{"{:?}", n};
}
}
./numbers.rs:12:25: 12:29 error: cannot move out of borrowed content
./numbers.rs:12 return Some(self.number);
How to implement Iterator for boxed values properly?
This comes down to Rust’s ownership model and the distinction between copy and move semantics; Box<T> has move semantics, not implementing Copy, and so return Some(self.number); would move self.number, taking ownership of it; but this is not permitted because it would require consuming self, which is only taken by mutable reference.
You have a few choices (where I write “the object with move semantics,” I mean in this specific case self.number):
Don’t return the object with move semantics, return something else with copy semantics reference, such as a reference instead of the boxed value (returning a reference will require the iterator object to be different from the object being iterated over so that you can write the lifetime in Item; thus it doesn’t apply to your specific use case) or the unboxed number.
Construct a new value to return based on the object with move semantics:
impl Iterator for Numbers {
type Item = Box<usize>;
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
self.count -= 1;
Some(Box::new(self.number))
} else {
None
}
}
}
Clone the object with move semantics (this is a simplified form of the second option, really):
impl Iterator for Numbers {
type Item = Box<usize>;
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
self.count -= 1;
Some(self.number.clone())
} else {
None
}
}
}
Construct a new value to substitute in place of the object with move semantics:
use std::mem;
impl Iterator for Numbers {
type Item = Box<usize>;
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
self.count -= 1;
let number = mem::replace(&mut self.number, Box::new(0));
// self.number now contains 0
Some(number)
} else {
None
}
}
}
Related
Rather than taking every Nth element from an iterator which I can do with Iterator::step_by, I would like to skip every Nth element. How can I achieve this idiomatically? Is there maybe even a standard library or itertools function?
This is what I came up with to skip every 7th say. It requires enumerate, filter, and map, though one could use a filter_map instead of the latter two.
(0..100).enumerate()
.filter(|&(i, x)| (i + 1) % 7 != 0)
.map(|(i, x)| x);
How could I cast this into a function so that I could simply write:
(0..100).skip_every(7)
If you want to get the exact interface you asked for, your best option at this time is to implement a custom iterator adapter type. Here's a basic version of such a type:
pub struct SkipEvery<I> {
inner: I,
every: usize,
index: usize,
}
impl<I> SkipEvery<I> {
fn new(inner: I, every: usize) -> Self {
assert!(every > 1);
let index = 0;
Self {
inner,
every,
index,
}
}
}
impl<I: Iterator> Iterator for SkipEvery<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.every - 1 {
self.index = 1;
self.inner.nth(1)
} else {
self.index += 1;
self.inner.next()
}
}
}
pub trait IteratorSkipEveryExt: Iterator + Sized {
fn skip_every(self, every: usize) -> SkipEvery<Self> {
SkipEvery::new(self, every)
}
}
impl<I: Iterator + Sized> IteratorSkipEveryExt for I {}
(Playground)
A more complete implementation could also add optimized versions of further Iterator methods, as well as implementations of DoubleEndedIterator and ExactSizeIterator -- see the implementation of StepBy as an example.
Your code is pretty easy to turn into a function:
fn skip_every<I: Iterator> (iter: I, n: usize) -> impl Iterator<Item = <I as Iterator>::Item> {
iter.enumerate()
.filter_map(move |(i, v)| if (i + 1) % n != 0 { Some (v) } else { None })
}
fn main() {
println!("{:?}", skip_every (0..20, 7).collect::<Vec<_>>());
}
Playground
Or avoiding the expensive modulo:
fn skip_every2<I: Iterator> (iter: I, n: usize) -> impl Iterator<Item = <I as Iterator>::Item> {
iter.zip ((0..n).rev().cycle()).filter_map (|(v, i)| if i != 0 { Some (v) } else { None })
}
Playground
I have a custom iterator and I would like to optionally call .skip(...) in the custom .next() method. However, I get a type error because Skip != Iterator.
Sample code is as follows:
struct CrossingIter<'a, T> {
index: usize,
iter: std::slice::Iter<'a, T>,
}
impl<'a, T: Float> Iterator for CrossingIter<'a, T> {
type Item = (usize, T);
fn next(&mut self) -> Option<(usize, T)> {
let iter = (&mut self.iter).enumerate();
let iter = if self.index == 0 {
self.index += 3;
iter.skip(3)
} else {
iter
}
// lots of code here working with the new iterator
iter.next()
}
}
The issue is that after calling .skip(3), the type of iter has changed. One solution would be to duplicate the // lots of code ... in each branch of the if statement, but I'd rather not.
My question is: Is there a way to conditionally apply skip(...) to an iterator and continue working with it without duplicating a bunch of code?
skip is designed to construct a new iterator, which is very useful in situations where you want your code to remain, at least on the surface, immutable. However, in your case, you want to advance the existing iterator while still leaving it valid.
There is advance_by which does what you want, but it's Nightly so it won't run on Stable Rust.
if self.index == 0 {
self.index += 3;
self.iter.advance_by(3);
}
We can abuse nth to get what we want, but it's not very idiomatic.
if self.index == 0 {
self.index += 3;
self.iter.nth(2);
}
If I saw that code in production, I'd be quite puzzled.
The simplest and not terribly satisfying answer is to just reimplement advance_by as a helper function. The source is available and pretty easy to adapt
fn my_advance_by(iter: &mut impl Iterator, n: usize) -> Result<(), usize> {
for i in 0..n {
iter.next().ok_or(i)?;
}
Ok(())
}
All this being said, if your use case is actually just to skip the first three elements, all you need is to start with the skip call and assume your iterator is always Skip
struct CrossingIter<'a, T> {
index: usize,
iter: std::iter::Skip<std::slice::Iter<'a, T>>,
}
I think #Silvio's answer is a better perspective.
You may call skip(0) instead of the iter itself in else branch...
And the return value of the iterator generated by enumerate doesn't match your definition: fn next(&mut self) -> Option<(usize, T)>. You need to map it.
Here is a working example:
use num::Float;
struct CrossingIter<'a, T> {
index: usize,
iter: std::slice::Iter<'a, T>,
}
impl<'a, T: Float> Iterator for CrossingIter<'a, T> {
type Item = (usize, T);
fn next(&mut self) -> Option<(usize, T)> {
let iter = (&mut self.iter).enumerate();
let mut iter = if self.index == 0 {
self.index += 3;
iter.skip(3)
} else {
iter.skip(0)
};
// lots of code here working with the new iterator
iter.next().map(|(i, &v)| (i, v))
}
}
I have an iterator-type-object that can return zero, one or more items each time it's called. I want to implement a standard Iter API, i.e. next returns Option<Self::Item>, so it can be consumed item by item.
In Clojure I would probably do this with mapcat ("map and concatenate").
My current solution (thanks to #Ryan) uses flat_map but still requires a lot of allocation:
// Desired input:
// A stateful object that implements an iterator which returns a number of results each time.
// The real code is a bit more complicated, this is the minimal example.
struct MyThing {
counter: i32,
}
impl Iterator for MyThing {
type Item = Vec<String>;
fn next(&mut self) -> Option<Vec<String>> {
self.counter += 1;
if self.counter == 4 {
self.counter = 1;
}
match self.counter {
1 => Some(vec!["One".to_string()]),
2 => Some(vec!["One".to_string(), "Two".to_string()]),
3 => Some(vec![
"One".to_string(),
"Two".to_string(),
"Three".to_string(),
]),
_ => Some(vec![]),
}
}
}
fn main() {
let things = MyThing { counter: 0 };
// Missing piece, though the following line does the job:
let flattened = things.flat_map(|x| x);
// However this requires a heap allocation at each loop.
// Desired output: I can iterate, item by item.
for item in flattened {
println!("{:?}", item);
}
}
Given the innovative things I have seen, I wonder if there's a more idiomatic, less expensive way of accomplishing this pattern.
If you know how to generate the "inner" values programmatically, replace Vec<String> with a struct you define that implements Iterator<Item = String>. (Technically only IntoIterator is necessary, but Iterator is sufficient.)
struct Inner {
index: usize,
stop: usize,
}
impl Inner {
fn new(n: usize) -> Self {
Inner { index: 0, stop: n }
}
}
impl Iterator for Inner {
type Item = String;
fn next(&mut self) -> Option<String> {
static WORDS: [&str; 3] = ["One", "Two", "Three"];
let result = if self.index < self.stop {
WORDS.get(self.index).map(|r| r.to_string())
} else {
None
};
self.index += 1;
result
}
}
Because Inner implements Iterator<Item = String>, it can be iterated over much like Vec<String>. But Inner does not have to pre-allocate a Vec and consume items one by one; it can lazily create each String on demand.
The "outer" iterator is just a struct that implements Iterator<Item = Inner>, likewise constructing each Inner lazily:
struct Outer {
counter: i32,
}
impl Iterator for Outer {
type Item = Inner;
fn next(&mut self) -> Option<Inner> {
self.counter = 1 + self.counter % 3;
Some(Inner::new(self.counter as usize))
}
}
As you know, Iterator::flat_map flattens nested structure, so something like the following works:
let things = Outer { counter: 0 };
for item in things.flat_map(|x| x).take(100) {
println!("{:?}", item);
}
In real-life code, Inner and Outer are probably pretty different from this example most of the time. For example, it's not necessarily possible to write Inner without doing the equivalent of allocating a Vec. So the precise shapes and semantics of these iterators depend on concrete information about the use case.
The above assumes that Inner is somehow useful, or easier to implement on its own. You could easily write a single struct that iterates over the sequence without needing to be flattened, but you have to also put the inner iterator state (the index field) into Outer:
struct Outer {
index: usize,
counter: i32,
}
impl Iterator for Outer {
type Item = String;
fn next(&mut self) -> Option<String> {
static WORDS: [&str; 3] = ["One", "Two", "Three"];
let result = WORDS.get(self.index).map(|r| r.to_string());
self.index += 1;
if self.index >= self.counter as usize {
self.counter = 1 + self.counter % 3;
self.index = 0;
};
result
}
}
fn main() {
let things = Outer { counter: 1, index: 0 };
for item in things.take(100) {
println!("{:?}", item);
}
}
In many other languages it's common to have APIs that go something like
obj.do_x()
.do_y()
In Rust I run into a problem, if do_x, do_y take &mut self, the types don't match. Is there an elegant way to solve this?
For example:
#[derive(Debug)]
struct Counter { count: u32 }
impl Counter {
fn incr(&mut self) -> &mut Counter {
self.count = self.count + 1;
self
}
fn new() -> Counter {
Counter {
count: 0
}
}
}
The problem is, new() returns a Counter, but the fluent API needs mut Counter.
Why would you use a reference?
#[derive(Debug)]
struct Counter { count: u32 }
impl Counter {
fn incr(mut self) -> Counter {
self.count = self.count + 1;
self
}
fn new() -> Counter {
Counter {
count: 0
}
}
}
If you consume the original, then there is no borrow issue any longer :)
Note: while appropriate for a builder pattern, it may be annoying with regular types.
You're correct, the types differ. You'll probably run in to lifetime issue. I assume you tried this:
let mut counter = Counter::new().incr().incr();
That fails. However, splitting them out:
let mut counter = Counter::new();
counter.incr().incr();
..works fine. The compiler will actually give you a decent hint here:
help: consider using a `let` binding to increase its lifetime
As I said in my comment.. to "work around" this fluent API design during object instantiation, people will commonly create a Builder type (the "Builder Pattern"). Yours, for example, might look like this:
#[derive(Debug)]
struct Counter { count: u32 }
struct CounterBuilder { count: u32 }
impl CounterBuilder {
fn new() -> CounterBuilder {
CounterBuilder {
count: 0
}
}
fn incr(&mut self) -> &mut CounterBuilder {
self.count = self.count + 1;
self
}
fn build(&self) -> Counter {
Counter {
count: self.count
}
}
}
fn main() {
let counter = CounterBuilder::new()
.incr()
.incr()
.build();
println!("Counter value is: {}", counter.count); // Should print 2
assert_eq!(2, counter.count);
}
Essentially, this works around the lifetime issues by discarding the borrow after the build call (its noting that you're finished with an instance of a CounterBuilder)... at which point you have a new concrete Counter object constructed and ready to go.
Once you have your Counter instantiated... you can then modify it via its own fluent API if you want.. e.g:
let mut counter = CounterBuilder::new()
.incr()
.incr()
.build();
counter.local_increment().local_increment(); // For example, if you were to add a "local_increment" fluent method to Counter
I'm trying to implement an iterator which will yield prime numbers. I store already found prime numbers in a Vec<u64>.
Here's my implementation:
struct Primes {
primes: Vec<u64>,
}
impl Primes {
fn new() -> Primes {
Primes { primes: vec!(2, 3) }
}
fn iter(&self) -> PrimesIterator {
PrimesIterator { primes: &self.primes, index : 0 }
}
}
struct PrimesIterator<'a> {
primes: & 'a Vec<u64>,
index: usize,
}
impl<'a> Iterator for PrimesIterator<'a> {
type Item = u64;
fn next(&mut self) -> Option<u64> {
if self.index < self.primes.len() {
let result = self.primes[self.index];
self.index += 1;
Some(result)
} else {
let mut n = *self.primes.last().unwrap();
loop {
n += 2;
if is_prime(self.primes, n) {
self.primes.push(n);
self.index += 1;
return Some(n);
}
}
}
}
}
fn is_prime(primes: &[u64], n: u64) -> bool {
for &p in primes.iter() {
if n % p == 0 {
return false;
}
if p * p > n {
return true;
}
}
return false;
}
but when I'm trying to compile it, I'm getting the following error:
main.rs: error: cannot borrow immutable borrowed content `*self.primes` as mutable
main.rs: self.primes.push(n);
I declared self as &mut so I don't really understand what's wrong here and how to fix that.
Your PrimesIterator type contains a non-mutable reference to a Vec<u64>. You need to declare it as a mutable reference:
struct PrimesIterator<'a> {
primes: &'a mut Vec<u64>,
index: usize,
}
This will of course require you to also modify the iter() function to make sure it passes a mutable reference:
impl Primes {
fn new() -> Primes {
Primes { primes: vec!(2, 3) }
}
fn iter(&mut self) -> PrimesIterator {
PrimesIterator { primes: &mut self.primes, index : 0 }
}
}