- Hands-On Data Structures and Algorithms with Rust
- Claus Matzinger
- 386字
- 2021-07-02 14:11:51
Adding entries
The transaction log can now be created and hold entries, but there is no way to add anything to the list. Typically, a list has the ability to add elements to either end—as long as there is a pointer to that end. If that was not the case, any operation would become computationally expensive, since every item has to be looked at to find its successor. With a pointer to the end (tail) of the list, this won't be the case for the append operation; however, to access a random index on the list, it would require some time to go through everything.
This is one of the things that a linked list does really well—adding items to either end. There are a few critical things that should not be overlooked, though:
- Creating the Node object within the method makes for a nicer API and better ownership handling.
- Edge cases such as empty lists.
- Incrementing the length is a good idea.
- The RefCell is used to retrieve mutable ownership for setting a new successor using its borrow_mut() function (interior mutability).
Once that is thought of, the actual implementation is not too bad. Rust's Option type offers a method to retrieve ownership of a value it contains, replacing it with None (see also the documentations for Option.take()—https://doc.rust-lang.org/std/option/enum.Option.html#method.take and mem::replace()—https://doc.rust-lang.org/stable/std/mem/fn.replace.html), which conveniently shortens the code required to append a new node:
pub fn append(&mut self, value: String) {
let new = Node::new(value);
match self.tail.take() {
Some(old) => old.borrow_mut().next = Some(new.clone()),
None => self.head = Some(new.clone())
};
self.length += 1;
self.tail = Some(new);
}
With that, it's now possible to create a log of any string commands passing through. However, there is something important missing here as well: log replay.