-1

I'm looking for some way to shorten an iterator by some condition. A bit like an inverse filter but it stops iterating at the first true value. Let's call it until(f). Where:

iterator.until(f)

Would return an iterator that only runs until f is true once.

Let's use an example of finding the next prime number.

We have some structure containing known primes and a function to extend it.

// Structure for caching known prime numbers
struct PrimeGenerator {
    primes:Vec<i64>
}

impl PrimeGenerator {

    // Create a new prime generator
    fn new()->Self{
        let primes = vec![2,3];
        Self {
            primes,
        }
    }
    
    // Extend the list of known primes by 1
    fn extend_by_one(&mut self){
        let mut next_option = self.primes.last().unwrap()+2;
        while self.primes.iter().any(|x| next_option%x == 0) { // This is the relevant line
            next_option += 2;
        }
        self.primes.push(next_option);
    }

}

Now this snippet is a bit too exhaustive as we should only have to check until the square root of next_option, so I was looking for a some method that would shorten the iterator based on some condition, so I could write something like:

self.iter().until(|x| x*x > next_option).any(|x| next_option%x == 0)

Is there any similar pattern available?

iHnR
  • 125
  • 7
  • 4
    Do you mean [take_while](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.take_while)? Please read the docs of `Iterator` before asking about such trivial things. – cafce25 Dec 10 '22 at 14:53
  • @cafce25 While it is a trivial question, I think it has its purpose, given that SO's primary goal is to be a huge Q&A. – Finomnis Dec 10 '22 at 15:24
  • 2
    Yes Q&A not copy of the documentation. Doing research is expressly one of the prerequisites to asking a question here. And reading the documentation on the item the question is about imo is an essential part of that. That being said I don't think this is not exceptionally bad and going in with the expectation of a name `until` one might overlook take_while. That's why I didn't donwvote. @Finomnis – cafce25 Dec 10 '22 at 15:25
  • @cafce25 I agree with that. – Finomnis Dec 10 '22 at 15:26
  • @cafce25 Either way, I would have created an answer, but I can't create an example because the given code is incomplete. `PrimeGenerator` does not implement `.iter()`. So I'd vote to close as incomplete. – Finomnis Dec 10 '22 at 15:28
  • @cafce25 keep in mind that the iterator documentation page has about a hundred documented functions, not counting everything else. If you're not used to reading Rust documentation, and you don't know what you are looking for, it's easy to overlook things. And SO is a good place to have the documentation "indexed by need". Some very-high scoring questions are just asking about something that can be found in the documentation (look at [how to exit Vim](https://stackoverflow.com/questions/11828270/how-do-i-exit-vim)...) – jthulhu Dec 10 '22 at 15:32
  • @Finomnis Whoops you are correct. I shortened my code to make it more concise and it slipped through the cracks. – iHnR Dec 12 '22 at 16:23

1 Answers1

2

Looks like your until is similar to inverted take_while.

self.iter().take_while(|x| x*x <= next_option).all(|x| next_option%x != 0)
Miiao
  • 751
  • 1
  • 8