Rust implementation of linked list

I'm writing an implementation of linked list to learn rust. I have run into a problem with writing the function pop_first element of the linked list. Rust telling me that I can't assign to immutable.

#[derive(Debug)]
enum List {
    Cons(i32, Box<List>),
    Nil
}


fn pop_first(&mut self) -> Option<i32> {
    type_of("self", &self);
    match *self{
        List::Cons(value, ref mut next) => {
            type_of("next", &next);
            self = next;
            Some(value)
        },
        List::Nil => None,
    }
}

When I run list.pop_first(), i get the "can't not assign to immutable argument

error[E0384]: cannot assign to immutable argument `self`
  --> src/main.rs:44:17
   |
44 |                 self = next;
   |                 ^^^^^^^^^^^ cannot assign to immutable argument

error: aborting due to previous error

Can someone point out what I have done wrong?

Assigning to self would just mutate the local variable self, but this function wants to mutate *self (the thing that self points to). To do this, you'll need to assign a new value of type List, but next has type &mut List.

std::mem::replace is one useful way to move a value out of a mutable reference, by putting a new value in its place:

    use std::mem::replace;
    
    match *self {
        List::Cons(value, ref mut next) => {
            let tail = replace(next, Box::new(List::Nil));
            *self = *tail;
            Some(value)
        },
        List::Nil => None,
    }

(Playground)

By the way, you might be interested in this tutorial: Learning Rust With Entirely Too Many Linked Lists

1 Like

A slightly simpler way to write this would be:

    match replace(self, List::Nil) {
        List::Cons(value, next) => {
            *self = *next;
            Some(value)
        },
        List::Nil => None,
    }

Thank you. I used your solution and it worked. I'm reading through your link and it's quite interesting.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.