Hee Hwang
Hee Hwang

Reputation: 141

Deleting duplicates from a single linked list

pub fn delete_duplicates(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
    let mut head = head;
    let mut cur = head.as_mut();
    while cur.is_some() && cur.as_ref().unwrap().next.is_some() {
        if cur.as_ref().unwrap().val == cur.as_ref().unwrap().next.as_ref().unwrap().val {
            //let next = cur.unwrap().next.as_mut().unwrap().next.take();  (1) Error!
            let next = cur.as_mut().unwrap().next.as_mut().unwrap().next.take();  // (2) Ok
            cur.as_mut().unwrap().next = next;
        }
        else {
            //cur = cur.as_ref().unwrap().next.as_mut();  (3) Error!
            cur = cur.unwrap().next.as_mut();  // (4) Ok
        }
    }
    head
}

The code above deletes duplicates inside a custom single linked list. (e.g. [1,1,2] -> [1,2])
Using (2) and (4) compiles and does what the program is supposed to do.
(1) and (3) generate compiler error and I just can't grasp what is happening here.

Upvotes: 1

Views: 123

Answers (1)

0x00A5
0x00A5

Reputation: 1792

I have created a reproducible playground. Other folks, please use it to help and correct me if my answer is wrong.

For (1), when you call cur.unwrap(), the value (Option<&mut Box<ListNode>>) got moved from cur. but when you call cur.as_mut(), it gave you a Option<&mut &mut Box<ListNode>>, and unwrapping it doesn't move cur's value. I created a small playground code snippet to illustrate this.

For (3), it has two errors.

  1. when you call cur.as_ref(), the value is behind a &, so you cannot access its value but then borrowed it as mutable again when you call as_mut()

  2. if you replace the as_ref() call in (3) with a as_mut() call, you will see only the other error.

    Line 28, Char 17: cannot assign to `cur` because it is borrowed (solution.rs)
       |
    28 |                 cur = cur.as_mut().unwrap().next.as_mut();
       |                 ^^^^^^---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |                 |     |
       |                 |     borrow of `cur` occurs here
       |                 assignment to borrowed `cur` occurs here
       |                 borrow later used here
    error: aborting due to previous error
    

    You cannot first borrow cur's value, reassign cur with a new value, then use the borrowed value. Playground to illustrate this.

For (4), yes, it consumes cur's value, which is a Option<&mut Box<ListNode>>, not Option<Box<ListNode>>, so it is OK.

Upvotes: 2

Related Questions