New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New post: Refactoring Rust, Primitive Obsession #22

Merged
merged 3 commits into from Nov 28, 2016

Conversation

Projects
None yet
4 participants
@IanWhitney
Owner

IanWhitney commented Sep 1, 2016

No description provided.

type IntoIter = ::std::vec::IntoIter<char>;
fn into_iter(self) -> Self::IntoIter {
self.input.chars().collect::<Vec<char>>().into_iter()

This comment has been minimized.

@Ms2ger

Ms2ger Sep 1, 2016

I would suggest instead implementing IntoIterator like this:

impl<'a> IntoIterator for &'a Brackets {
    type Item = char;
    type IntoIter = ::std::str::Chars<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.input.chars()
    }
}

This avoids allocating a vector for no particular reason.

@Ms2ger

Ms2ger Sep 1, 2016

I would suggest instead implementing IntoIterator like this:

impl<'a> IntoIterator for &'a Brackets {
    type Item = char;
    type IntoIter = ::std::str::Chars<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.input.chars()
    }
}

This avoids allocating a vector for no particular reason.

This comment has been minimized.

@IanWhitney

IanWhitney Sep 1, 2016

Owner

Thanks! I tried that but could not get the lifetime annotations correct and decided it in favor of the simpler-looking (if less efficient) vector approach.

@IanWhitney

IanWhitney Sep 1, 2016

Owner

Thanks! I tried that but could not get the lifetime annotations correct and decided it in favor of the simpler-looking (if less efficient) vector approach.

This comment has been minimized.

@IanWhitney

IanWhitney Sep 1, 2016

Owner

I've updated the post to link to your non-vector impl.

@IanWhitney

IanWhitney Sep 1, 2016

Owner

I've updated the post to link to your non-vector impl.

@hroi

This comment has been minimized.

Show comment
Hide comment
@hroi

hroi Sep 1, 2016

More generic:

struct Brackets<S> {
    input: S,
}

impl<S> From<S> for Brackets<S> {
    fn from(input: S) -> Self {
        Brackets { input: input }
    }
}

impl<S> IntoIterator for Brackets<S> where S: AsRef<str> {
    type Item = char;
    type IntoIter = ::std::vec::IntoIter<char>;

    fn into_iter(self) -> Self::IntoIter {
        self.input.as_ref().chars().collect::<Vec<char>>().into_iter()
    }
}

pub fn are_balanced<S>(input: S) -> bool
    where S: AsRef<str>
{
    let input = input.as_ref();
    let brackets = Brackets::from(input);
    let mut unmatched_brackets: Vec<char> = Vec::new();

    for current_bracket in brackets.into_iter() {
        if let Some(most_recent_unmatched) = unmatched_brackets.pop() {
            let is_matched = match (most_recent_unmatched, current_bracket) {
                ('[', ']') => true,
                ('{', '}') => true,
                ('(', ')') => true,
                _ => false,
            };
            if !is_matched {
                unmatched_brackets.push(most_recent_unmatched);
                unmatched_brackets.push(current_bracket);
            }
        } else {
            unmatched_brackets.push(current_bracket);
        }
    }

    unmatched_brackets.is_empty()
}

fn main() {
    assert!(are_balanced("{[]}".to_string()));
    assert!(!are_balanced("[{]}")); // works on primitive strs as well
}

hroi commented Sep 1, 2016

More generic:

struct Brackets<S> {
    input: S,
}

impl<S> From<S> for Brackets<S> {
    fn from(input: S) -> Self {
        Brackets { input: input }
    }
}

impl<S> IntoIterator for Brackets<S> where S: AsRef<str> {
    type Item = char;
    type IntoIter = ::std::vec::IntoIter<char>;

    fn into_iter(self) -> Self::IntoIter {
        self.input.as_ref().chars().collect::<Vec<char>>().into_iter()
    }
}

pub fn are_balanced<S>(input: S) -> bool
    where S: AsRef<str>
{
    let input = input.as_ref();
    let brackets = Brackets::from(input);
    let mut unmatched_brackets: Vec<char> = Vec::new();

    for current_bracket in brackets.into_iter() {
        if let Some(most_recent_unmatched) = unmatched_brackets.pop() {
            let is_matched = match (most_recent_unmatched, current_bracket) {
                ('[', ']') => true,
                ('{', '}') => true,
                ('(', ')') => true,
                _ => false,
            };
            if !is_matched {
                unmatched_brackets.push(most_recent_unmatched);
                unmatched_brackets.push(current_bracket);
            }
        } else {
            unmatched_brackets.push(current_bracket);
        }
    }

    unmatched_brackets.is_empty()
}

fn main() {
    assert!(are_balanced("{[]}".to_string()));
    assert!(!are_balanced("[{]}")); // works on primitive strs as well
}
@IanWhitney

This comment has been minimized.

Show comment
Hide comment
@IanWhitney

IanWhitney Sep 2, 2016

Owner

@hroi, thanks. I'm guessing generics will show up later in this series of posts, a little early to introduce them in the first entry.

Owner

IanWhitney commented Sep 2, 2016

@hroi, thanks. I'm guessing generics will show up later in this series of posts, a little early to introduce them in the first entry.

@wigy-opensource-developer

This comment has been minimized.

Show comment
Hide comment
@wigy-opensource-developer

wigy-opensource-developer Sep 27, 2016

I love the idea of this series of articles. Keep on the good work! Do you have a schedule for the next article?

I love the idea of this series of articles. Keep on the good work! Do you have a schedule for the next article?

@IanWhitney

This comment has been minimized.

Show comment
Hide comment
@IanWhitney

IanWhitney Sep 28, 2016

Owner

@wigy-opensource-developer I'm glad you like it. I wish I could commit to a schedule right now, but life is making that hard! As soon as I'm able.

Owner

IanWhitney commented Sep 28, 2016

@wigy-opensource-developer I'm glad you like it. I wish I could commit to a schedule right now, but life is making that hard! As soon as I'm able.

@IanWhitney IanWhitney merged commit bc8d4b9 into master Nov 28, 2016

@IanWhitney IanWhitney deleted the primitive_obsession branch Nov 28, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment