Reputation: 5730
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
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