I am learning Rust and practicing on Linked Lists, whereby I want to get to a solution that doesn't involve a .clone()
at the end.
Here's the smallest useful MVP code I can come up with (Rust Playground):
#![allow(unused)]
fn main() {
let v: Option<Box<ListNode>> = None;
println!("{:?}", v);
let result2 = get_nth_node(v, 3);
println!(" --> {:?}", result2);
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
fn get_nth_node(head: Option<Box<ListNode>>, n:usize) -> Option<Box<ListNode>> {
if head.is_none() {
return None;
}
let mut count = 1;
let mut ptr: &Option<Box<ListNode>> = &head;
while count < n {
count += 1;
match ptr {
None => return None,
Some(v) => ptr = &v.next
}
}
return (*ptr);
}
This yields an error on moving and borrowing:
error[E0507]: cannot move out of `*ptr` which is behind a shared reference
--> src/main.rs:30:12
|
30 | return (*ptr);
| ^^^^^^
| |
| move occurs because `*ptr` has type `std::option::Option<std::boxed::Box<ListNode>>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `(*ptr).as_ref()`
I understand why changing the function to return (*ptr).clone()
works, but it seems superfluous.
My two main questions:
- What specifically is the shared reference that
*ptr
is behind? - Is there a better way, conceptually, to work with this in Rust?
ptr
is a shared (immutable) reference:*ptr
is behind that reference.Well you could just not work with references since you're taking the list by value and are therefore consuming it:
Alternatively, you could work with refs (that would probably be a better idea really):