Skip to content

Commit 3df38f6

Browse files
Merge pull request #2847 from LukasKalbertodt/fix-linked-list-cursor-names
Fix linked list cursor names
2 parents 81c6deb + 772fb67 commit 3df38f6

File tree

1 file changed

+103
-94
lines changed

1 file changed

+103
-94
lines changed

text/2570-linked-list-cursors.md

Lines changed: 103 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,21 @@ list many times. With the cursor interface, one can do the following:
6161

6262
``` rust
6363
fn remove_replace<T, P, F>(list: &mut LinkedList<T>, p: P, f: F)
64-
where P: Fn(&T) -> bool, F: Fn(T) -> T
64+
where P: Fn(&T) -> bool, F: Fn(T) -> T
6565
{
66-
let mut cursor = list.cursor_mut();
67-
// move to the first element, if it exists
68-
loop {
69-
let should_replace = match cursor.peek() {
70-
Some(element) => p(element),
71-
None => break,
72-
};
73-
if should_replace {
74-
let old_element = cursor.pop().unwrap();
75-
cursor.insert(f(old_element));
76-
}
77-
cursor.move_next();
78-
}
66+
let mut cursor = list.cursor_front_mut();
67+
// move to the first element, if it exists
68+
loop {
69+
let should_replace = match cursor.peek_next() {
70+
Some(element) => p(element),
71+
None => break,
72+
};
73+
if should_replace {
74+
let old_element = cursor.remove_current().unwrap();
75+
cursor.insert_after(f(old_element));
76+
}
77+
cursor.move_next();
78+
}
7979
}
8080
```
8181

@@ -84,31 +84,31 @@ iterator, perform operations on it and collect. This is easier, however it still
8484
requires much needless allocation.
8585

8686
For another example, consider code that was previously using `IterMut`
87-
extensions.
87+
extensions.
8888
``` rust
8989
fn main() {
90-
let mut list: LinkedList<_> = (0..10).collect();
91-
let mut iter = list.iter_mut();
92-
while let Some(x) = iter.next() {
93-
if x >= 5 {
94-
break;
95-
}
96-
}
97-
iter.insert_next(12);
90+
let mut list: LinkedList<_> = (0..10).collect();
91+
let mut iter = list.iter_mut();
92+
while let Some(x) = iter.next() {
93+
if x >= 5 {
94+
break;
95+
}
96+
}
97+
iter.insert_next(12);
9898
}
9999
```
100100
This can be changed almost verbatim to `CursorMut`:
101101
``` rust
102102
fn main() {
103-
let mut list: LinkedList<_> = (0..10).collect();
104-
let mut cursor = list.cursor_mut() {
105-
while let Some(x) = cursor.peek_next() {
106-
if x >= 5 {
107-
break;
108-
}
109-
cursor.move_next();
110-
}
111-
cursor.insert(12);
103+
let mut list: LinkedList<_> = (0..10).collect();
104+
let mut cursor = list.cursor_front_mut() {
105+
while let Some(x) = cursor.peek_next() {
106+
if x >= 5 {
107+
break;
108+
}
109+
cursor.move_next();
110+
}
111+
cursor.insert_after(12);
112112
}
113113
```
114114
In general, the cursor interface is not the easiest way to do something.
@@ -122,90 +122,99 @@ One gets a cursor the exact same way as one would get an iterator. The
122122
returned cursor would point to the "empty" element, i.e. if you got an element
123123
and called `current` you would receive `None`.
124124
``` rust
125-
// Provides a cursor to the first element of the list
126-
pub fn cursor(&self) -> Cursor<T>;
125+
/// Provides a cursor to the first element of the list.
126+
pub fn cursor_front(&self) -> Cursor<T>;
127127

128-
/// Provides a cursor with mutable references and access to the list
129-
pub fn cursor_mut(&mut self) -> CursorMut<T>;
128+
/// Provides a mutable cursor to the first element of the list.
129+
pub fn cursor_front_mut(&mut self) -> CursorMut<T>;
130+
131+
/// Provides a cursor to the last element of the list.
132+
pub fn cursor_back(&self) -> Cursor<T>;
133+
134+
/// Provides a mutable cursor to the last element of the list.
135+
pub fn cursor_back_mut(&mut self) -> CursorMut<T>;
130136
```
131137

132138
These would provide the following interface:
133139

134140
``` rust
135141
impl<'list, T> Cursor<'list, T> {
136-
/// Move to the subsequent element of the list if it exists or the empty
137-
/// element
138-
pub fn move_next(&mut self);
139-
/// Move to the previous element of the list
140-
pub fn move_prev(&mut self);
141-
142-
/// Get the current element
143-
pub fn current(&self) -> Option<&'list T>;
144-
/// Get the following element
145-
pub fn peek(&self) -> Option<&'list T>;
146-
/// Get the previous element
147-
pub fn peek_before(&self) -> Option<&'list T>;
142+
/// Returns the cursor position index within the `LinkedList`.
143+
pub fn index(&self) -> Option<usize>;
144+
145+
/// Move to the subsequent element of the list if it exists or the empty
146+
/// element
147+
pub fn move_next(&mut self);
148+
/// Move to the previous element of the list
149+
pub fn move_prev(&mut self);
150+
151+
/// Get the current element
152+
pub fn current(&self) -> Option<&'list T>;
153+
/// Get the following element
154+
pub fn peek_next(&self) -> Option<&'list T>;
155+
/// Get the previous element
156+
pub fn peek_prev(&self) -> Option<&'list T>;
148157
}
149158

150159
impl<'list T> CursorMut<'list, T> {
151-
/// Move to the subsequent element of the list if it exists or the empty
152-
/// element
153-
pub fn move_next(&mut self);
154-
/// Move to the previous element of the list
155-
pub fn move_prev(&mut self);
156-
157-
/// Get the current element
158-
pub fn current(&mut self) -> Option<&mut T>;
159-
/// Get the next element
160-
pub fn peek(&mut self) -> Option<&mut T>;
161-
/// Get the previous element
162-
pub fn peek_before(&mut self) -> Option<&mut T>;
163-
164-
/// Get an immutable cursor at the current element
165-
pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T>;
166-
167-
// Now the list editing operations
168-
169-
/// Insert `item` after the cursor
170-
pub fn insert(&mut self, item: T);
171-
/// Insert `item` before the cursor
172-
pub fn insert_before(&mut self, item: T);
173-
174-
/// Remove and return the item following the cursor
175-
pub fn pop(&mut self) -> Option<T>;
176-
/// Remove and return the item before the cursor
177-
pub fn pop_before(&mut self) -> Option<T>;
178-
179-
/// Insert `list` between the current element and the next
180-
pub fn insert_list(&mut self, list: LinkedList<T>);
181-
/// Insert `list` between the previous element and current
182-
pub fn insert_list_before(&mut self, list: LinkedList<T>);
183-
184-
/// Split the list in two after the current element
185-
/// The returned list consists of all elements following the current one.
186-
// note: consuming the cursor is not necessary here, but it makes sense
187-
// given the interface
188-
pub fn split(self) -> LinkedList<T>;
189-
/// Split the list in two before the current element
190-
pub fn split_before(self) -> LinkedList<T>;
160+
/// Returns the cursor position index within the `LinkedList`.
161+
pub fn index(&self) -> Option<usize>;
162+
163+
/// Move to the subsequent element of the list if it exists or the empty
164+
/// element
165+
pub fn move_next(&mut self);
166+
/// Move to the previous element of the list
167+
pub fn move_prev(&mut self);
168+
169+
/// Get the current element
170+
pub fn current(&mut self) -> Option<&mut T>;
171+
/// Get the next element
172+
pub fn peek_next(&mut self) -> Option<&mut T>;
173+
/// Get the previous element
174+
pub fn peek_prev(&mut self) -> Option<&mut T>;
175+
176+
/// Get an immutable cursor at the current element
177+
pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T>;
178+
179+
// Now the list editing operations
180+
181+
/// Insert `item` after the cursor
182+
pub fn insert_after(&mut self, item: T);
183+
/// Insert `item` before the cursor
184+
pub fn insert_before(&mut self, item: T);
185+
186+
/// Remove the current item. The new current item is the item following the
187+
/// removed one.
188+
pub fn remove_current(&mut self) -> Option<T>;
189+
190+
/// Insert `list` between the current element and the next
191+
pub fn splice_after(&mut self, list: LinkedList<T>);
192+
/// Insert `list` between the previous element and current
193+
pub fn splice_before(&mut self, list: LinkedList<T>);
194+
195+
/// Split the list in two after the current element
196+
/// The returned list consists of all elements following the current one.
197+
pub fn split_after(&mut self) -> LinkedList<T>;
198+
/// Split the list in two before the current element
199+
pub fn split_before(&mut self) -> LinkedList<T>;
191200
}
192201
```
193202
One should closely consider the lifetimes in this interface. Both `Cursor` and
194203
`CursorMut` operate on data in their `LinkedList`. This is why, they both hold
195204
the annotation of `'list`.
196205

197206
The lifetime elision for their constructors is correct as
198-
```
199-
pub fn cursor(&self) -> Cursor<T>
207+
```rust
208+
pub fn cursor_front(&self) -> Cursor<T>
200209
```
201210
becomes
202-
```
203-
pub fn cursor<'list>(&'list self) -> Cursor<'list, T>
211+
```rust
212+
pub fn cursor_front<'list>(&'list self) -> Cursor<'list, T>
204213
```
205214
which is what we would expect. (the same goes for `CursorMut`).
206215

207-
Since `Cursor` cannot mutate its list, `current`, `peek` and `peek_before` all
208-
live as long as `'list`. However, in `CursorMut` we must be careful to make
216+
Since `Cursor` cannot mutate its list, `current`, `peek_next` and `peek_prev`
217+
all live as long as `'list`. However, in `CursorMut` we must be careful to make
209218
these methods borrow. Otherwise, one could produce multiple mutable references
210219
to the same element.
211220

0 commit comments

Comments
 (0)