russoue
russoue

Reputation: 5730

The best way to print a singly linked list in rust

In my effort to learn rust, I am trying to find the best way to print a singly linked list of structs in rust. Here is the code I have:

struct SList {
    n: int,
    next: Option<Box<SList>>
}

fn print_slist(mut l: &SList) {
    print!("{}", l.n);
    loop {
        match l.next {
            Some(ref next) => { print!(" -> {}", next.n); l = &(**next); },
            None => { break; }
        }
    }
    println!("");
}

fn main() {
    let sl1 = SList { n: 11, next: Some(box SList { n: 22, next: Some(box SList { n: 33, next: None })})};
    print_slist(&sl1);
}

I am sure this can be done in better ways and I would like to know them. Apart from that I am concerned about the &(**next) part. Is it creating an unnecessary copy of the next SList?

Upvotes: 3

Views: 1436

Answers (1)

Chris Morgan
Chris Morgan

Reputation: 90832

What you have works fine, with next being of type &Box<SList>, and so &**next is of type &SList.

You can, however, tidy it up by dereferencing the box in the pattern and getting &SList immediately.

Some(box ref next) => {
    print!(" -> {}", next.n);
    l = next;
},

I would also recommend writing such a thing as this in terms of an iterator. Also implementing std::fmt::Show instead of writing a separate function.

Here is an example implementation of both iteration and implementing Show:

use std::fmt;

struct SList {
    n: int,
    next: Option<Box<SList>>
}

struct SListIter<'a> {
    current: Option<&'a SList>,
}

impl SList {
    fn iter<'a>(&'a self) -> SListIter<'a> {
        SListIter {
            current: Some(self),
        }
    }
}

impl<'a> Iterator<int> for SListIter<'a> {
    fn next(&mut self) -> Option<int> {
        self.current.map(|current| {
            let value = current.n;
            self.current = match current.next {
                Some(box ref next) => Some(next),
                None => None
            };
            value
        })
    }
}

impl fmt::Show for SList {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut first = true;
        for value in self.iter() {
            if !first {
                try!(write!(f, " -> "));
            }
            try!(write!(f, "{}", value));
            first = false;
        }
        Ok(())
    }
}

fn main() {
    let sl1 = SList { n: 11, next: Some(box SList { n: 22, next: Some(box SList { n: 33, next: None })})};
    println!("{}", sl1);
}

Upvotes: 4

Related Questions