Hi,
I'm a C/C++ developer and new to Rust; I'm coding linklist as an exercise.
In C/C++, it's a common practice to pass a vector's reference as function parameter to modify the vector, e..g,
void get_nodes(linklist *list, &vector<Node*> v)
{
// get a bunch of nodes as pointers, node0 and node1 are pointers to node
v.push_back(node0);
v.push_back(node1);
}
In Rust, I do the same but encountered some problems related to mutable/immutable ownership. Appreciate your help!
Here is a reproducible code (also available in Playground)
use std::cell::RefCell;
struct MyNode
{
val: i32,
desc: String,
next: Option<Box<MyNode>>
}
impl MyNode
{
pub fn new(i: i32, d: &Option<String>) -> Self
{
MyNode
{
val: I,
desc: match(d) {None=>{"".to_string()} Some(dd)=>{dd.clone()}},
next: None
}
}
}
struct MyList
{
root: Option<Box<MyNode>>
}
impl MyList
{
pub fn new() -> MyList
{
MyList
{
root: Some( Box::new( MyNode::new( 0, &Some( "root".to_string() ) ) ) )
}
}
pub fn get_root(&mut self) -> &mut Option<Box<MyNode>>
{
return (&mut self.root);
}
pub fn get_range_node<'a>(&'a mut self, v2: &'a mut Vec<&'a Option<Box<MyNode>>>) // &mut Vec<&mut Box<MyNode>>
{
let mut head = self.get_root();
let mut curr = head.as_ref();
loop
{
// https://web.stanford.edu/class/cs110l/lecture-notes/lecture-06/
if (curr.is_none())
{
break;
}
// print!("*** {}\n", curr.unwrap().val);
let mut next = &curr.unwrap().next;
v2.push (&mut next);
curr = next.as_ref();
}
for i in 0..v2.len()
{
if (v2[i].is_some())
{
// println!("###{}:{}", i, v2[i].as_ref().unwrap().val);
}
}
}
pub fn get_tail(&mut self) -> &mut Option<Box<MyNode>>
{
let mut curr = self.get_root();
loop
{
if curr.as_ref().unwrap().next.is_none()
{
break;
}
else
{
curr = &mut curr.as_mut().unwrap().next;
}
}
return curr;
}
pub fn insert(&mut self, i: i32)
{
let new_node = Some( Box::new(MyNode::new(i, &Some(i.to_string() ))));
let tail = self.get_tail();
tail.as_mut().unwrap().next = new_node;
}
pub fn traverse(&mut self)
{
let mut curr = self.get_root();
let mut i = 0;
loop
{
if (curr.is_none())
{
break;
}
else
{
println!("[{}]: {}, desc:{:?}", i, curr.as_ref().unwrap().val, curr.as_ref().unwrap().desc);
curr = &mut curr.as_mut().unwrap().next;
i += 1;
}
}
}
}
#[test]
fn test_clean_list()
{
let n0 = MyNode::new(0, &Some("node0".to_string()));
let mut list = MyList::new();
let mut len:usize = 5;
// insert
for i in 0..len
{
list.insert(i as i32);
}
println!("Traverse list...");
list.traverse();
// Option1: access v
let mut v = vec![];
list.get_range_node(&mut v);
// Compiler error: immutable borrow occurs here; mutable borrow later used here
let v_len = &v.len();
// Option2: use RefCell
let mut v2 = RefCell::new(vec![]);
let mut v2_0 = v2.borrow_mut();
// Compiler error: borrowed value does not live long enough
list.get_range_node(&mut v2_0);
let v2_len = v2_0.len();
}