diff --git a/text/2570-linked-list-cursors.md b/text/2570-linked-list-cursors.md index 596e8078cca..cb2f8bf6a15 100644 --- a/text/2570-linked-list-cursors.md +++ b/text/2570-linked-list-cursors.md @@ -61,21 +61,21 @@ list many times. With the cursor interface, one can do the following: ``` rust fn remove_replace(list: &mut LinkedList, p: P, f: F) - where P: Fn(&T) -> bool, F: Fn(T) -> T + where P: Fn(&T) -> bool, F: Fn(T) -> T { - let mut cursor = list.cursor_mut(); - // move to the first element, if it exists - loop { - let should_replace = match cursor.peek() { - Some(element) => p(element), - None => break, - }; - if should_replace { - let old_element = cursor.pop().unwrap(); - cursor.insert(f(old_element)); - } - cursor.move_next(); - } + let mut cursor = list.cursor_front_mut(); + // move to the first element, if it exists + loop { + let should_replace = match cursor.peek_next() { + Some(element) => p(element), + None => break, + }; + if should_replace { + let old_element = cursor.remove_current().unwrap(); + cursor.insert_after(f(old_element)); + } + cursor.move_next(); + } } ``` @@ -84,31 +84,31 @@ iterator, perform operations on it and collect. This is easier, however it still requires much needless allocation. For another example, consider code that was previously using `IterMut` -extensions. +extensions. ``` rust fn main() { - let mut list: LinkedList<_> = (0..10).collect(); - let mut iter = list.iter_mut(); - while let Some(x) = iter.next() { - if x >= 5 { - break; - } - } - iter.insert_next(12); + let mut list: LinkedList<_> = (0..10).collect(); + let mut iter = list.iter_mut(); + while let Some(x) = iter.next() { + if x >= 5 { + break; + } + } + iter.insert_next(12); } ``` This can be changed almost verbatim to `CursorMut`: ``` rust fn main() { - let mut list: LinkedList<_> = (0..10).collect(); - let mut cursor = list.cursor_mut() { - while let Some(x) = cursor.peek_next() { - if x >= 5 { - break; - } - cursor.move_next(); - } - cursor.insert(12); + let mut list: LinkedList<_> = (0..10).collect(); + let mut cursor = list.cursor_front_mut() { + while let Some(x) = cursor.peek_next() { + if x >= 5 { + break; + } + cursor.move_next(); + } + cursor.insert_after(12); } ``` In general, the cursor interface is not the easiest way to do something. @@ -122,72 +122,81 @@ One gets a cursor the exact same way as one would get an iterator. The returned cursor would point to the "empty" element, i.e. if you got an element and called `current` you would receive `None`. ``` rust -// Provides a cursor to the first element of the list -pub fn cursor(&self) -> Cursor; +/// Provides a cursor to the first element of the list. +pub fn cursor_front(&self) -> Cursor; -/// Provides a cursor with mutable references and access to the list -pub fn cursor_mut(&mut self) -> CursorMut; +/// Provides a mutable cursor to the first element of the list. +pub fn cursor_front_mut(&mut self) -> CursorMut; + +/// Provides a cursor to the last element of the list. +pub fn cursor_back(&self) -> Cursor; + +/// Provides a mutable cursor to the last element of the list. +pub fn cursor_back_mut(&mut self) -> CursorMut; ``` These would provide the following interface: ``` rust impl<'list, T> Cursor<'list, T> { - /// Move to the subsequent element of the list if it exists or the empty - /// element - pub fn move_next(&mut self); - /// Move to the previous element of the list - pub fn move_prev(&mut self); - - /// Get the current element - pub fn current(&self) -> Option<&'list T>; - /// Get the following element - pub fn peek(&self) -> Option<&'list T>; - /// Get the previous element - pub fn peek_before(&self) -> Option<&'list T>; + /// Returns the cursor position index within the `LinkedList`. + pub fn index(&self) -> Option; + + /// Move to the subsequent element of the list if it exists or the empty + /// element + pub fn move_next(&mut self); + /// Move to the previous element of the list + pub fn move_prev(&mut self); + + /// Get the current element + pub fn current(&self) -> Option<&'list T>; + /// Get the following element + pub fn peek_next(&self) -> Option<&'list T>; + /// Get the previous element + pub fn peek_prev(&self) -> Option<&'list T>; } impl<'list T> CursorMut<'list, T> { - /// Move to the subsequent element of the list if it exists or the empty - /// element - pub fn move_next(&mut self); - /// Move to the previous element of the list - pub fn move_prev(&mut self); - - /// Get the current element - pub fn current(&mut self) -> Option<&mut T>; - /// Get the next element - pub fn peek(&mut self) -> Option<&mut T>; - /// Get the previous element - pub fn peek_before(&mut self) -> Option<&mut T>; - - /// Get an immutable cursor at the current element - pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T>; - - // Now the list editing operations - - /// Insert `item` after the cursor - pub fn insert(&mut self, item: T); - /// Insert `item` before the cursor - pub fn insert_before(&mut self, item: T); - - /// Remove and return the item following the cursor - pub fn pop(&mut self) -> Option; - /// Remove and return the item before the cursor - pub fn pop_before(&mut self) -> Option; - - /// Insert `list` between the current element and the next - pub fn insert_list(&mut self, list: LinkedList); - /// Insert `list` between the previous element and current - pub fn insert_list_before(&mut self, list: LinkedList); - - /// Split the list in two after the current element - /// The returned list consists of all elements following the current one. - // note: consuming the cursor is not necessary here, but it makes sense - // given the interface - pub fn split(self) -> LinkedList; - /// Split the list in two before the current element - pub fn split_before(self) -> LinkedList; + /// Returns the cursor position index within the `LinkedList`. + pub fn index(&self) -> Option; + + /// Move to the subsequent element of the list if it exists or the empty + /// element + pub fn move_next(&mut self); + /// Move to the previous element of the list + pub fn move_prev(&mut self); + + /// Get the current element + pub fn current(&mut self) -> Option<&mut T>; + /// Get the next element + pub fn peek_next(&mut self) -> Option<&mut T>; + /// Get the previous element + pub fn peek_prev(&mut self) -> Option<&mut T>; + + /// Get an immutable cursor at the current element + pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T>; + + // Now the list editing operations + + /// Insert `item` after the cursor + pub fn insert_after(&mut self, item: T); + /// Insert `item` before the cursor + pub fn insert_before(&mut self, item: T); + + /// Remove the current item. The new current item is the item following the + /// removed one. + pub fn remove_current(&mut self) -> Option; + + /// Insert `list` between the current element and the next + pub fn splice_after(&mut self, list: LinkedList); + /// Insert `list` between the previous element and current + pub fn splice_before(&mut self, list: LinkedList); + + /// Split the list in two after the current element + /// The returned list consists of all elements following the current one. + pub fn split_after(&mut self) -> LinkedList; + /// Split the list in two before the current element + pub fn split_before(&mut self) -> LinkedList; } ``` One should closely consider the lifetimes in this interface. Both `Cursor` and @@ -195,17 +204,17 @@ One should closely consider the lifetimes in this interface. Both `Cursor` and the annotation of `'list`. The lifetime elision for their constructors is correct as -``` -pub fn cursor(&self) -> Cursor +```rust +pub fn cursor_front(&self) -> Cursor ``` becomes -``` -pub fn cursor<'list>(&'list self) -> Cursor<'list, T> +```rust +pub fn cursor_front<'list>(&'list self) -> Cursor<'list, T> ``` which is what we would expect. (the same goes for `CursorMut`). -Since `Cursor` cannot mutate its list, `current`, `peek` and `peek_before` all -live as long as `'list`. However, in `CursorMut` we must be careful to make +Since `Cursor` cannot mutate its list, `current`, `peek_next` and `peek_prev` +all live as long as `'list`. However, in `CursorMut` we must be careful to make these methods borrow. Otherwise, one could produce multiple mutable references to the same element.