Merge pull request #2847 from LukasKalbertodt/fix-linked-list-cursor-names

Fix linked list cursor names
This commit is contained in:
Mark Rousskov 2020-01-14 10:44:15 -05:00 committed by GitHub
commit 3df38f62c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 96 additions and 87 deletions

View File

@ -61,21 +61,21 @@ list many times. With the cursor interface, one can do the following:
``` rust
fn remove_replace<T, P, F>(list: &mut LinkedList<T>, 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<T>;
/// Provides a cursor to the first element of the list.
pub fn cursor_front(&self) -> Cursor<T>;
/// Provides a cursor with mutable references and access to the list
pub fn cursor_mut(&mut self) -> CursorMut<T>;
/// Provides a mutable cursor to the first element of the list.
pub fn cursor_front_mut(&mut self) -> CursorMut<T>;
/// Provides a cursor to the last element of the list.
pub fn cursor_back(&self) -> Cursor<T>;
/// Provides a mutable cursor to the last element of the list.
pub fn cursor_back_mut(&mut self) -> CursorMut<T>;
```
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<usize>;
/// 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);
/// Returns the cursor position index within the `LinkedList`.
pub fn index(&self) -> Option<usize>;
/// 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>;
/// 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 an immutable cursor at the current element
pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T>;
/// 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>;
// Now the list editing operations
/// Get an immutable cursor at the current element
pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T>;
/// 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);
// Now the list editing operations
/// Remove and return the item following the cursor
pub fn pop(&mut self) -> Option<T>;
/// Remove and return the item before the cursor
pub fn pop_before(&mut self) -> Option<T>;
/// 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);
/// Insert `list` between the current element and the next
pub fn insert_list(&mut self, list: LinkedList<T>);
/// Insert `list` between the previous element and current
pub fn insert_list_before(&mut self, list: LinkedList<T>);
/// Remove the current item. The new current item is the item following the
/// removed one.
pub fn remove_current(&mut self) -> Option<T>;
/// 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<T>;
/// Split the list in two before the current element
pub fn split_before(self) -> LinkedList<T>;
/// Insert `list` between the current element and the next
pub fn splice_after(&mut self, list: LinkedList<T>);
/// Insert `list` between the previous element and current
pub fn splice_before(&mut self, list: LinkedList<T>);
/// 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<T>;
/// Split the list in two before the current element
pub fn split_before(&mut self) -> LinkedList<T>;
}
```
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<T>
```rust
pub fn cursor_front(&self) -> Cursor<T>
```
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.