Skip to content

Commit 4c0bebf

Browse files
committed
Collection views is RFC 60
1 parent 5d66c8e commit 4c0bebf

File tree

1 file changed

+23
-23
lines changed

1 file changed

+23
-23
lines changed

active/0000-collection-views.md active/0060-collection-views.md

+23-23
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
- Start Date: 2014-08-28
2-
- RFC PR: (leave this empty)
3-
- Rust Issue: (leave this empty)
2+
- RFC PR: (https://github.com/rust-lang/rfcs/pull/216)
3+
- Rust Issue: (https://github.com/rust-lang/rust/issues/17320)
44

55
# Summary
66

7-
Add additional iterator-like Entry objects to collections.
7+
Add additional iterator-like Entry objects to collections.
88
Entries provide a composable mechanism for in-place observation and mutation of a
99
single element in the collection, without having to "re-find" the element multiple times.
1010
This deprecates several "internal mutation" methods like hashmap's `find_or_insert_with`.
@@ -47,7 +47,7 @@ combinatorially explosive. They all seem to return a mutable reference to the re
4747
accessed "just in case", and `find_with_or_insert_with` takes a magic argument `a` to
4848
try to work around the fact that the *two* closures it requires can't both close over
4949
the same value (even though only one will ever be called). `find_with_or_insert_with`
50-
is also actually performing the role of `insert_with_or_update_with`,
50+
is also actually performing the role of `insert_with_or_update_with`,
5151
suggesting that these aren't well understood.
5252

5353
Rust has been in this position before: internal iteration. Internal iteration was (author's note: I'm told)
@@ -58,13 +58,13 @@ composability. Thus, this RFC proposes the same solution to the internal mutatio
5858
# Detailed design
5959

6060
A fully tested "proof of concept" draft of this design has been implemented on top of hashmap,
61-
as it seems to be the worst offender, while still being easy to work with. You can
61+
as it seems to be the worst offender, while still being easy to work with. You can
6262
[read the diff here](https://github.com/Gankro/rust/commit/39a1fa7c7362a3e22e59ab6601ac09475daff39b).
6363

6464
All the internal mutation methods are replaced with a single method on a collection: `entry`.
6565
The signature of `entry` will depend on the specific collection, but generally it will be similar to
6666
the signature for searching in that structure. `entry` will in turn return an `Entry` object, which
67-
captures the *state* of a completed search, and allows mutation of the area.
67+
captures the *state* of a completed search, and allows mutation of the area.
6868

6969
For convenience, we will use the hashmap draft as an example.
7070

@@ -110,23 +110,23 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
110110
}
111111
```
112112

113-
There are definitely some strange things here, so let's discuss the reasoning!
113+
There are definitely some strange things here, so let's discuss the reasoning!
114114

115-
First, `entry` takes a `key` by value, because this is the observed behaviour of the internal mutation
116-
methods. Further, taking the `key` up-front allows implementations to avoid *validating* provided keys if
117-
they require an owned `key` later for insertion. This key is effectively a *guarantor* of the entry.
115+
First, `entry` takes a `key` by value, because this is the observed behaviour of the internal mutation
116+
methods. Further, taking the `key` up-front allows implementations to avoid *validating* provided keys if
117+
they require an owned `key` later for insertion. This key is effectively a *guarantor* of the entry.
118118

119119
Taking the key by-value might change once collections reform lands, and Borrow and ToOwned are available.
120-
For now, it's an acceptable solution, because in particular, the primary use case of this functionality
121-
is when you're *not sure* if you need to insert, in which case you should be prepared to insert.
120+
For now, it's an acceptable solution, because in particular, the primary use case of this functionality
121+
is when you're *not sure* if you need to insert, in which case you should be prepared to insert.
122122
Otherwise, `find_mut` is likely sufficient.
123123

124124
The result is actually an enum, that will either be Occupied or Vacant. These two variants correspond
125-
to concrete types for when the key matched something in the map, and when the key didn't, repsectively.
125+
to concrete types for when the key matched something in the map, and when the key didn't, repsectively.
126126

127127
If there isn't a match, the user has exactly one option: insert a value using `set`, which will also insert
128128
the guarantor, and destroy the Entry. This is to avoid the costs of maintaining the structure, which
129-
otherwise isn't particularly interesting anymore.
129+
otherwise isn't particularly interesting anymore.
130130

131131
If there is a match, a more robust set of options is provided. `get` and `get_mut` provide access to the
132132
value found in the location. `set` behaves as the vacant variant, but also yields the old value. `take`
@@ -151,23 +151,23 @@ One can now write something equivalent to the "intuitive" inefficient code, but
151151
`insert_or_update` methods. In fact, this matches so closely to the inefficient manipulation
152152
that users could reasonable ignore Entries *until performance becomes an issue*. At which point
153153
it's an almost trivial migration. Closures also aren't needed to dance around the fact that one may
154-
want to avoid generating some values unless they have to, because that falls naturally out of
154+
want to avoid generating some values unless they have to, because that falls naturally out of
155155
normal control flow.
156156

157157
If you look at the actual patch that does this, you'll see that Entry itself is exceptionally
158158
simple to implement. Most of the logic is trivial. The biggest amount of work was just
159159
capturing the search state correctly, and even that was mostly a cut-and-paste job.
160160

161-
With Entries, the gate is also opened for... *adaptors*!
162-
Really want `insert_or_update` back? That can be written on top of this generically with ease.
161+
With Entries, the gate is also opened for... *adaptors*!
162+
Really want `insert_or_update` back? That can be written on top of this generically with ease.
163163
However, such discussion is out-of-scope for this RFC. Adaptors can
164164
be tackled in a back-compat manner after this has landed, and usage is observed. Also, this
165165
proposal does not provide any generic trait for Entries, preferring concrete implementations for
166166
the time-being.
167167

168168
# Drawbacks
169169

170-
* More structs, and more methods in the short-term
170+
* More structs, and more methods in the short-term
171171

172172
* More collection manipulation "modes" for the user to think about
173173

@@ -176,17 +176,17 @@ found in the examples
176176

177177
# Alternatives
178178

179-
* Just put our foot down, say "no efficient complex manipulations", and drop
179+
* Just put our foot down, say "no efficient complex manipulations", and drop
180180
all the internal mutation stuff without a replacement.
181181

182182
* Try to build out saner/standard internal manipulation methods.
183183

184-
* Try to make this functionality a subset of [Cursors](http://discuss.rust-lang.org/t/pseudo-rfc-cursors-reversible-iterators/386/7),
184+
* Try to make this functionality a subset of [Cursors](http://discuss.rust-lang.org/t/pseudo-rfc-cursors-reversible-iterators/386/7),
185185
which would be effectively a bi-directional mut_iter
186-
where the returned references borrow the cursor preventing aliasing/safety issues,
187-
so that mutation can be performed at the location of the cursor.
186+
where the returned references borrow the cursor preventing aliasing/safety issues,
187+
so that mutation can be performed at the location of the cursor.
188188
However, preventing invalidation would be more expensive, and it's not clear that
189-
cursor semantics would make sense on e.g. a HashMap, as you can't insert *any* key
189+
cursor semantics would make sense on e.g. a HashMap, as you can't insert *any* key
190190
in *any* location.
191191

192192
* This RFC originally [proposed a design without enums that was substantially more complex]

0 commit comments

Comments
 (0)