Skip to content

Commit 8aa4dad

Browse files
committed
CollectionsMoveIndices: expand the comment about trees
1 parent 670df6d commit 8aa4dad

File tree

1 file changed

+41
-7
lines changed

1 file changed

+41
-7
lines changed

test/Prototypes/CollectionsMoveIndices.swift

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@
100100
// 2. We can't specify constraints on associated types. This forces many
101101
// trivial algorithms to specify useless constraints.
102102
//
103+
// Solution: constraints on associated types are a desirable
104+
// language feature, part of the Swift generics model. This issue
105+
// will be fixed by compiler improvements.
106+
//
103107
// Trees
104108
// =====
105109
//
@@ -150,18 +154,26 @@
150154
// reuse, then the tree nodes can't have parent pointers (a node
151155
// can have multiple different parents in different trees). This
152156
// means that it is not possible to advance an index in O(1). If
153-
// we need to go up the tree while advancing the index, we would
154-
// need to traverse the tree starting from the root in O(log n).
157+
// we need to go up the tree while advancing the index, without
158+
// parent pointers we would need to traverse the tree starting from
159+
// the root in O(log n).
160+
//
155161
// Thus, index has to essentially store a path through the tree
156162
// from the root to the node (it is usually possible to encode this
157163
// path in a 64-bit number). Since the index stores the path,
158164
// subscripting on such an index would also cost O(log n).
159165
//
160-
// We should note that even though the operations mentioned cost
161-
// O(log n), the base of the logarithm would be typically large
162-
// (e.g., 32), and the size of the machine memory is limited.
163-
// Thus, we could treat the complexity as effectively constant for
164-
// all practical purposes.
166+
// We should note that persistent trees typically use B-trees, so
167+
// the base of the logarithm would be typically large (e.g., 32).
168+
// We also know that the size of the RAM is limited. Thus, we
169+
// could treat the O(log n) complexity as effectively constant for
170+
// all practical purposes. But the constant factor will be much
171+
// larger than in other designs.
172+
//
173+
// Swift's collection index model does not change anything as
174+
// compared to other languages. The important point is that the
175+
// proposed index model allows such implementations of persistent
176+
// collections.
165177
//
166178
// 2. Trees with O(1) subscripting and advancing.
167179
//
@@ -208,13 +220,35 @@
208220
// extra data structure would only increase the constant factor
209221
// on memory overhead.
210222
//
223+
// | (1) | (2)(a) | (2)(b)
224+
// -------------------------------------+----------+---------+-------
225+
// memory-safe | Yes | Yes | Yes
226+
// indices are not reference-counted | Yes | Yes | Yes
227+
// shares nodes | Yes | No | No
228+
// subscripting on an index | O(log n) | O(1) | O(1)
229+
// advancing an index | O(log n) | O(1) | O(1)
230+
// deleting does not invalidate indices | No | No | Yes
231+
// requires extra O(n) storage just ... | | |
232+
// for safety checks | No | No | Yes
233+
//
211234
// Each of the designs discussed above has its uses, but the intuition
212235
// is that (2)(a) is the one most commonly needed in practice. (2)(a)
213236
// does not have the desired index invalidation properties. There is
214237
// a small number of commonly used algorithms that require that
215238
// property, and they can be provided as methods on the collection,
216239
// for example removeAll(in: Range<Index>) and
217240
// removeAll(_: (Element)->Bool).
241+
//
242+
// If we were to allow reference-counted indices (basically, the
243+
// current collections model), then an additional design is possible
244+
// -- let's call it (2)(c) for the purpose of discussion. This design
245+
// would be like (2)(b), but won't require extra storage that is used
246+
// only for safety checks. Instead, every index would pay a RC
247+
// penalty and carry a strong reference to the tree node.
248+
//
249+
// Note that (2)(c) is still technically possible to implement in the
250+
// new collection index model, it just goes against a goal of having
251+
// indices free of reference-counted stored properties.
218252

219253
infix operator ...* { associativity none precedence 135 }
220254
infix operator ..<* { associativity none precedence 135 }

0 commit comments

Comments
 (0)