These are chat archives for rust-lang/rust

14th
May 2017
Fra ns
@snarf95_twitter
May 14 2017 12:49 UTC
Im trying to make my own groupby iterator for strings just for exercising. I'm having trouble expression the stribg as an iterator of chars and using it inside my iterator, currently using vec of chars as source 'iterator' any advice or resources on writing iterators?
Denis Lisov
@tanriol
May 14 2017 13:37 UTC
@snarf95_twitter What kind of problems are you having? Are you trying a custom iterator for RLE?
Fra ns
@snarf95_twitter
May 14 2017 14:36 UTC
struct Run {
    token: char,
    runs: u8,
}

struct RunLengthEncoder {
    inner: Vec<char>,
    pos: usize,
}

impl Iterator for RunLengthEncoder {
    type Item = Run;

    fn next(&mut self) -> Option<Self::Item> {
        if self.pos >= self.inner.len() {
            None
        } else {
            let mut current_token = self.inner[self.pos].clone();
            let mut runs = 1;
            self.pos += 1;

            while self.pos < self.inner.len() && current_token == self.inner[self.pos].clone() {
                self.pos += 1;
                runs += 1;
            }

            Some(Run {
                     token: current_token,
                     runs: runs,
                 })
        }
    }
}

impl RunLengthEncoder {
    pub fn new(chars: Vec<char>) -> RunLengthEncoder {
        RunLengthEncoder {
            inner: chars,
            pos: 0,
        }
    }
}

pub fn encode(input: &str) -> String {
    let iter = RunLengthEncoder::new(input.chars().collect());
    iter.map(|r| if r.runs > 1 {
                 format!("{}{}", r.runs, r.token)
             } else {
                 format!("{}", r.token)
             })
        .collect()
}
I would like to avoid cloning the vec and instead use a iterator..
Denis Lisov
@tanriol
May 14 2017 18:08 UTC
@snarf95_twitter Well, I'd go for something like this
There are places that can be micro-optimized, but I tend to beleive in the optimizer unless proven wrong.
Sergey Noskov
@Albibek
May 14 2017 18:17 UTC
shouldn't it be the u8 array for RLE to work correctly?
Fra ns
@snarf95_twitter
May 14 2017 18:22 UTC
That's really nice. I tried to make inner be of type iterator but that's not possible since it's a trait.
I guess peekable is really what I want here so good!
Fra ns
@snarf95_twitter
May 14 2017 18:29 UTC
I'll try making the decode using your techniques
Denis Lisov
@tanriol
May 14 2017 19:12 UTC
@Albibek Well, nothing stops us from defining RLE on characters... anyway, this particular encoding uses the information from the exercise that there are no digits in the input string (and there are only ASCII letters and whitespace, so there's no difference).
Fra ns
@snarf95_twitter
May 14 2017 19:18 UTC
Yeah this exercise comes from exercism.io and one of the assumptions is that there'll be no digits
Fra ns
@snarf95_twitter
May 14 2017 20:05 UTC
why is this not possible?
let runs = self.inner.take_while(|x| x.clone() == next_char).count() as u8;
error[E0507]: cannot move out of borrowed content
Denis Lisov
@tanriol
May 14 2017 20:08 UTC
Look at the docs:
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where P: FnMut(&Self::Item) -> bool { ... }
Fra ns
@snarf95_twitter
May 14 2017 20:08 UTC
needs to be mut x?
Denis Lisov
@tanriol
May 14 2017 20:09 UTC
take_while consumes the iterator
Fra ns
@snarf95_twitter
May 14 2017 20:09 UTC
yeah, that's what I want?
Denis Lisov
@tanriol
May 14 2017 20:09 UTC
You definitely don't want to consume the whole iterator :-)
Fra ns
@snarf95_twitter
May 14 2017 20:09 UTC
as long as it doesn't consume the last element where the predicate fails
Denis Lisov
@tanriol
May 14 2017 20:10 UTC
It does.
Being more correct, it would.
Fra ns
@snarf95_twitter
May 14 2017 20:10 UTC
shame ;/
lol
Denis Lisov
@tanriol
May 14 2017 20:11 UTC
In fact, you cannot use the iterator again after applying take_while to it.
Fra ns
@snarf95_twitter
May 14 2017 20:11 UTC
let mut runs = 1;
while self.inner.peek().cloned() == Some(next_char) {
    runs += 1;
    self.inner.next();
}
going to do this instead then
why can I not use the iterator after doing take_while?
can this code not be written as a higher order function?
Denis Lisov
@tanriol
May 14 2017 20:13 UTC
The take_while method takes ownership of the iterator and does not return it (or any borrows). Thus you cannot do anything to it.
Fra ns
@snarf95_twitter
May 14 2017 20:14 UTC
could I clone the iterator?
this doesn't work either:
let runs = self.inner.clone().take_while(|mut x| x.clone() == next_char).count() as u8;
            self.inner.skip(runs as usize);
Denis Lisov
@tanriol
May 14 2017 20:15 UTC
You could clone it but I don't recommend doing that.
And, by the way, please stop using u8... it makes no sense in this case.
Fra ns
@snarf95_twitter
May 14 2017 20:18 UTC
what should I use instead of u8?
Denis Lisov
@tanriol
May 14 2017 20:19 UTC
This code can be written as a higher order function using some additional features from the itertools crate.
Fra ns
@snarf95_twitter
May 14 2017 20:20 UTC
yeah the group_by right?
I'm just exercising making a custom iterator.. what makes me surprised is that it isn't possible to use other iter methods inside next?
Denis Lisov
@tanriol
May 14 2017 20:21 UTC
I'd suggest using usize as your number corresponds to a value up to a length of some string, which is limited by the address space.
Sure it is possible. In some cases.
Denis Lisov
@tanriol
May 14 2017 20:27 UTC
Not necessarily group_by. Here's another variant.
Fra ns
@snarf95_twitter
May 14 2017 20:36 UTC
so this is the code so far
very fun exercise thanks for help :)
peeking_take_while that's some smooth code
hope that itertools will someday become part of core
Denis Lisov
@tanriol
May 14 2017 20:41 UTC
Let's see version 1.0 first :-)
Fra ns
@snarf95_twitter
May 14 2017 20:43 UTC
versions are just numbers :smile:
Denis Lisov
@tanriol
May 14 2017 20:45 UTC
Versions are not just numbers, but stability promises :-)
Fra ns
@snarf95_twitter
May 14 2017 20:47 UTC
so nothing bad is going to happen once it hits 1.0.0?
Denis Lisov
@tanriol
May 14 2017 20:53 UTC
Well, I think nothing bad will happen... but everyone has one's own understanding of 'bad'...
Ingvar Stepanyan
@RReverser
May 14 2017 21:16 UTC
@snarf95_twitter @tanriol reading your discussion - curious, why wouldn't skip_while work for that use case?
because you need to know how many you skipped or ...?
Denis Lisov
@tanriol
May 14 2017 21:18 UTC
Yes, we need to know the number of elements skipped.
Ingvar Stepanyan
@RReverser
May 14 2017 21:18 UTC
I see
you could probably combine with enumerate or something similar
then index of the next element after skipping would be your length
Denis Lisov
@tanriol
May 14 2017 21:22 UTC
Hm... yes, probably we could :-)