pythonic-fp-circulararray 6.0.0__py3-none-any.whl → 6.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- # Copyright 2023-202 Geoffrey R. Scheller
1
+ # Copyright 2023-2026 Geoffrey R. Scheller
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -13,19 +13,16 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- Variable Storage Capacity
17
- =========================
16
+ .. admonition:: Variable storage capacity circular array CA
18
17
 
19
- **Circular array with variable storage capacity.**
20
-
21
- - O(1) pops either end
22
- - O(1) amortized pushes either end
23
- - O(1) indexing, fully supports slicing
24
- - auto-resizing more storage capacity when necessary, manually compatible
25
- - iterable, safely mutates while iterators iterating over previous state
26
- - comparisons compare identity before equality, like builtins
27
- - in boolean context, falsy when empty, otherwise truthy
28
- - function ``ca`` produces auto-resizing circular array from arguments
18
+ - O(1) pops either end
19
+ - O(1) amortized pushes either end
20
+ - O(1) indexing, fully supports slicing
21
+ - auto-resizing more storage capacity when necessary, manually compatible
22
+ - iterable, safely mutates while iterators iterating over previous state
23
+ - comparisons compare identity before equality, like builtins
24
+ - in boolean context, falsy when empty, otherwise truthy
25
+ - function ``ca`` produces auto-resizing circular array from arguments
29
26
 
30
27
  """
31
28
 
@@ -38,24 +35,25 @@ __all__ = ['CA', 'ca']
38
35
  nada: Final[NoValue] = NoValue()
39
36
 
40
37
 
41
- class CA[I]:
42
- __slots__ = '_items', '_cnt', '_cap', '_front', '_rear'
38
+ class CA[X]:
39
+ __slots__ = '_xs', '_cnt', '_cap', '_front', '_rear'
43
40
 
44
- def __init__(self, *items: Iterable[I]) -> None:
41
+ def __init__(self, *xs: Iterable[X]) -> None:
45
42
  """
46
- :param items: "Optionally" takes a single iterable to populate circular array.
47
- :raises TypeError: When ``items[0]`` not iterable.
43
+ :param xs: Optionally takes a single iterable to initially populate the circular array.
44
+ :raises TypeError: When ``xs[0]`` not iterable.
48
45
  :raises ValueError: If more than 1 iterable is given.
46
+
49
47
  """
50
- if (size := len(items)) > 1:
48
+ if (size := len(xs)) > 1:
51
49
  msg = f'CA expects at most 1 argument, got {size}'
52
50
  raise ValueError(msg)
53
51
  if size:
54
- values: list[I | NoValue] = list(cast(Iterable[I | NoValue], items[0]))
55
- self._items = [nada] + values + [nada]
52
+ values: list[X | NoValue] = list(cast(Iterable[X | NoValue], xs[0]))
53
+ self._xs = [nada] + values + [nada]
56
54
  else:
57
- self._items = [nada, nada]
58
- self._cap = (cap := len(self._items))
55
+ self._xs = [nada, nada]
56
+ self._cap = (cap := len(self._xs))
59
57
  self._cnt = cap - 2
60
58
  if cap == 2:
61
59
  self._front = 0
@@ -67,21 +65,21 @@ class CA[I]:
67
65
  def _double_storage_capacity(self) -> None:
68
66
  if self._front <= self._rear:
69
67
  (
70
- self._items,
68
+ self._xs,
71
69
  self._cap,
72
70
  ) = (
73
- self._items + [nada] * self._cap,
71
+ self._xs + [nada] * self._cap,
74
72
  self._cap * 2,
75
73
  )
76
74
  else:
77
75
  (
78
- self._items,
76
+ self._xs,
79
77
  self._front,
80
78
  self._cap,
81
79
  ) = (
82
- self._items[: self._front]
80
+ self._xs[: self._front]
83
81
  + [nada] * self._cap
84
- + self._items[self._front :],
82
+ + self._xs[self._front :],
85
83
  self._front + self._cap,
86
84
  2 * self._cap,
87
85
  )
@@ -93,7 +91,7 @@ class CA[I]:
93
91
  self._cap,
94
92
  self._front,
95
93
  self._rear,
96
- self._items,
94
+ self._xs,
97
95
  ) = (
98
96
  2,
99
97
  0,
@@ -105,12 +103,12 @@ class CA[I]:
105
103
  self._cap,
106
104
  self._front,
107
105
  self._rear,
108
- self._items,
106
+ self._xs,
109
107
  ) = (
110
108
  3,
111
109
  1,
112
110
  1,
113
- [nada, self._items[self._front], nada],
111
+ [nada, self._xs[self._front], nada],
114
112
  )
115
113
  case _:
116
114
  if self._front <= self._rear:
@@ -118,30 +116,30 @@ class CA[I]:
118
116
  self._cap,
119
117
  self._front,
120
118
  self._rear,
121
- self._items,
119
+ self._xs,
122
120
  ) = (
123
121
  self._cnt + 2,
124
122
  1,
125
123
  self._cnt,
126
- [nada] + self._items[self._front : self._rear + 1] + [nada],
124
+ [nada] + self._xs[self._front : self._rear + 1] + [nada],
127
125
  )
128
126
  else:
129
127
  (
130
128
  self._cap,
131
129
  self._front,
132
130
  self._rear,
133
- self._items,
131
+ self._xs,
134
132
  ) = (
135
133
  self._cnt + 2,
136
134
  1,
137
135
  self._cnt,
138
136
  [nada]
139
- + self._items[self._front :]
140
- + self._items[: self._rear + 1]
137
+ + self._xs[self._front :]
138
+ + self._xs[: self._rear + 1]
141
139
  + [nada],
142
140
  )
143
141
 
144
- def __iter__(self) -> Iterator[I]:
142
+ def __iter__(self) -> Iterator[X]:
145
143
  if self._cnt > 0:
146
144
  (
147
145
  capacity,
@@ -152,15 +150,15 @@ class CA[I]:
152
150
  self._cap,
153
151
  self._rear,
154
152
  self._front,
155
- self._items.copy(),
153
+ self._xs.copy(),
156
154
  )
157
155
 
158
156
  while position != rear:
159
- yield cast(I, current_state[position])
157
+ yield cast(X, current_state[position])
160
158
  position = (position + 1) % capacity
161
- yield cast(I, current_state[position])
159
+ yield cast(X, current_state[position])
162
160
 
163
- def __reversed__(self) -> Iterator[I]:
161
+ def __reversed__(self) -> Iterator[X]:
164
162
  if self._cnt > 0:
165
163
  (
166
164
  capacity,
@@ -171,18 +169,26 @@ class CA[I]:
171
169
  self._cap,
172
170
  self._front,
173
171
  self._rear,
174
- self._items.copy(),
172
+ self._xs.copy(),
175
173
  )
176
174
 
177
175
  while position != front:
178
- yield cast(I, current_state[position])
176
+ yield cast(X, current_state[position])
179
177
  position = (position - 1) % capacity
180
- yield cast(I, current_state[position])
178
+ yield cast(X, current_state[position])
181
179
 
182
180
  def __repr__(self) -> str:
181
+ """
182
+ :returns: String of the form ``ca(x1, x2, ..., xn)``.
183
+
184
+ """
183
185
  return 'ca(' + ', '.join(map(repr, self)) + ')'
184
186
 
185
187
  def __str__(self) -> str:
188
+ """
189
+ :returns: String of the form ``(|x1, x2, ..., xn|)``.
190
+
191
+ """
186
192
  return '(|' + ', '.join(map(str, self)) + '|)'
187
193
 
188
194
  def __bool__(self) -> bool:
@@ -192,20 +198,20 @@ class CA[I]:
192
198
  return self._cnt
193
199
 
194
200
  @overload
195
- def __getitem__(self, idx: int) -> I: ...
201
+ def __getitem__(self, idx: int) -> X: ...
196
202
  @overload
197
- def __getitem__(self, idx: slice) -> 'CA[I]': ...
203
+ def __getitem__(self, idx: slice) -> 'CA[X]': ...
198
204
 
199
- def __getitem__(self, idx: int | slice) -> I | 'CA[I]':
205
+ def __getitem__(self, idx: int | slice) -> X | 'CA[X]':
200
206
  if isinstance(idx, slice):
201
207
  return CA(list(self)[idx])
202
208
 
203
209
  cnt = self._cnt
204
210
  if 0 <= idx < cnt:
205
- return cast(I, self._items[(self._front + idx) % self._cap])
211
+ return cast(X, self._xs[(self._front + idx) % self._cap])
206
212
 
207
213
  if -cnt <= idx < 0:
208
- return cast(I, self._items[(self._front + cnt + idx) % self._cap])
214
+ return cast(X, self._xs[(self._front + cnt + idx) % self._cap])
209
215
 
210
216
  if cnt == 0:
211
217
  msg0 = 'Trying to get a value from an empty CA.'
@@ -217,24 +223,24 @@ class CA[I]:
217
223
  raise IndexError(msg1 + msg2 + msg3)
218
224
 
219
225
  @overload
220
- def __setitem__(self, idx: int, vals: I) -> None: ...
226
+ def __setitem__(self, idx: int, vals: X) -> None: ...
221
227
  @overload
222
- def __setitem__(self, idx: slice, vals: Iterable[I]) -> None: ...
228
+ def __setitem__(self, idx: slice, vals: Iterable[X]) -> None: ...
223
229
 
224
- def __setitem__(self, idx: int | slice, vals: I | Iterable[I]) -> None:
230
+ def __setitem__(self, idx: int | slice, vals: X | Iterable[X]) -> None:
225
231
  if isinstance(idx, slice):
226
232
  if isinstance(vals, Iterable):
227
233
  item_list = list(self)
228
234
  item_list[idx] = vals
229
235
  _ca = CA(item_list)
230
236
  (
231
- self._items,
237
+ self._xs,
232
238
  self._cnt,
233
239
  self._cap,
234
240
  self._front,
235
241
  self._rear,
236
242
  ) = (
237
- _ca._items,
243
+ _ca._xs,
238
244
  _ca._cnt,
239
245
  _ca._cap,
240
246
  _ca._front,
@@ -247,9 +253,9 @@ class CA[I]:
247
253
 
248
254
  cnt = self._cnt
249
255
  if 0 <= idx < cnt:
250
- self._items[(self._front + idx) % self._cap] = cast(I, vals)
256
+ self._xs[(self._front + idx) % self._cap] = cast(X, vals)
251
257
  elif -cnt <= idx < 0:
252
- self._items[(self._front + cnt + idx) % self._cap] = cast(I, vals)
258
+ self._xs[(self._front + cnt + idx) % self._cap] = cast(X, vals)
253
259
  else:
254
260
  if cnt < 1:
255
261
  msg0 = 'Trying to index into an empty CA.'
@@ -269,13 +275,13 @@ class CA[I]:
269
275
  del item_list[idx]
270
276
  _ca = CA(item_list)
271
277
  (
272
- self._items,
278
+ self._xs,
273
279
  self._cnt,
274
280
  self._cap,
275
281
  self._front,
276
282
  self._rear,
277
283
  ) = (
278
- _ca._items,
284
+ _ca._xs,
279
285
  _ca._cnt,
280
286
  _ca._cap,
281
287
  _ca._front,
@@ -284,6 +290,13 @@ class CA[I]:
284
290
  del _ca
285
291
 
286
292
  def __eq__(self, other: object) -> bool:
293
+ """
294
+ :param other: The object to be compared to.
295
+ :returns: ``True`` if object is another ``CA`` whose items compare
296
+ as equal to the corresponding items in the ``CA``,
297
+ otherwise ``False``.
298
+
299
+ """
287
300
  if self is other:
288
301
  return True
289
302
  if not isinstance(other, type(self)):
@@ -310,28 +323,33 @@ class CA[I]:
310
323
 
311
324
  for nn in range(cnt1):
312
325
  if (
313
- self._items[(front1 + nn) % capacity1]
314
- is other._items[(front2 + nn) % capacity2]
326
+ self._xs[(front1 + nn) % capacity1]
327
+ is other._xs[(front2 + nn) % capacity2]
315
328
  ):
316
329
  continue
317
330
  if (
318
- self._items[(front1 + nn) % capacity1]
319
- != other._items[(front2 + nn) % capacity2]
331
+ self._xs[(front1 + nn) % capacity1]
332
+ != other._xs[(front2 + nn) % capacity2]
320
333
  ):
321
334
  return False
322
335
  return True
323
336
 
324
- def pushl(self, *items: I) -> None:
325
- """Push ``items`` on from left.
337
+ def pushl(self, *xs: X) -> None:
338
+ """
339
+ .. admonition:: Push left
340
+
341
+ Push items from the left onto the ``CA`` in the
342
+ order they were iterated.
343
+
344
+ :param xs: Items to be pushed onto the front of the circular array from the left.
326
345
 
327
- :param items: Items pushed onto circular array from left (front).
328
346
  """
329
- for item in items:
347
+ for item in xs:
330
348
  if self._cnt == self._cap:
331
349
  self._double_storage_capacity()
332
350
  (
333
351
  self._front,
334
- self._items[self._front],
352
+ self._xs[self._front],
335
353
  self._cnt,
336
354
  ) = (
337
355
  (self._front - 1) % self._cap,
@@ -339,17 +357,22 @@ class CA[I]:
339
357
  self._cnt + 1,
340
358
  )
341
359
 
342
- def pushr(self, *items: I) -> None:
343
- """Push ``items`` on from right.
360
+ def pushr(self, *xs: X) -> None:
361
+ """
362
+ .. admonition:: Push right
363
+
364
+ Push items from the right onto the ``CA`` in the
365
+ order they were iterated.
366
+
367
+ :param xs: Items to be pushed onto the rear of the ``CA`` from the right.
344
368
 
345
- :param items: Items pushed onto circular array from right (rear).
346
369
  """
347
- for item in items:
370
+ for item in xs:
348
371
  if self._cnt == self._cap:
349
372
  self._double_storage_capacity()
350
373
  (
351
374
  self._rear,
352
- self._items[self._rear],
375
+ self._xs[self._rear],
353
376
  self._cnt,
354
377
  ) = (
355
378
  (self._rear + 1) % self._cap,
@@ -357,20 +380,24 @@ class CA[I]:
357
380
  self._cnt + 1,
358
381
  )
359
382
 
360
- def popl(self) -> I:
361
- """Pop single item off from left side.
383
+ def popl(self) -> X:
384
+ """
385
+ .. admonition:: Pop left
386
+
387
+ Pop a single items off the left side of the ``CA``.
362
388
 
363
389
  :returns: Item popped from left side (front) of circular array.
364
390
  :raises ValueError: When called on an empty circular array.
391
+
365
392
  """
366
393
  if self._cnt > 1:
367
394
  (
368
395
  d,
369
- self._items[self._front],
396
+ self._xs[self._front],
370
397
  self._front,
371
398
  self._cnt,
372
399
  ) = (
373
- self._items[self._front],
400
+ self._xs[self._front],
374
401
  nada,
375
402
  (self._front + 1) % self._cap,
376
403
  self._cnt - 1,
@@ -378,12 +405,12 @@ class CA[I]:
378
405
  elif self._cnt == 1:
379
406
  (
380
407
  d,
381
- self._items[self._front],
408
+ self._xs[self._front],
382
409
  self._cnt,
383
410
  self._front,
384
411
  self._rear,
385
412
  ) = (
386
- self._items[self._front],
413
+ self._xs[self._front],
387
414
  nada,
388
415
  0,
389
416
  0,
@@ -392,22 +419,26 @@ class CA[I]:
392
419
  else:
393
420
  msg = 'Method popl called on an empty CA'
394
421
  raise ValueError(msg)
395
- return cast(I, d)
422
+ return cast(X, d)
423
+
424
+ def popr(self) -> X:
425
+ """
426
+ .. admonition:: Pop right
396
427
 
397
- def popr(self) -> I:
398
- """Pop single item off from right.
428
+ Pop a single items off the right side of the ``CA``.
399
429
 
400
430
  :returns: Item popped from right side (rear) of circular array.
401
431
  :raises ValueError: When called on an empty circular array.
432
+
402
433
  """
403
434
  if self._cnt > 1:
404
435
  (
405
436
  d,
406
- self._items[self._rear],
437
+ self._xs[self._rear],
407
438
  self._rear,
408
439
  self._cnt,
409
440
  ) = (
410
- self._items[self._rear],
441
+ self._xs[self._rear],
411
442
  nada,
412
443
  (self._rear - 1) % self._cap,
413
444
  self._cnt - 1,
@@ -415,12 +446,12 @@ class CA[I]:
415
446
  elif self._cnt == 1:
416
447
  (
417
448
  d,
418
- self._items[self._front],
449
+ self._xs[self._front],
419
450
  self._cnt,
420
451
  self._front,
421
452
  self._rear,
422
453
  ) = (
423
- self._items[self._front],
454
+ self._xs[self._front],
424
455
  nada,
425
456
  0,
426
457
  0,
@@ -429,39 +460,53 @@ class CA[I]:
429
460
  else:
430
461
  msg = 'Method popr called on an empty CA'
431
462
  raise ValueError(msg)
432
- return cast(I, d)
463
+ return cast(X, d)
464
+
465
+ def popld(self, default: X) -> X:
466
+ """
467
+ .. admonition:: Pop Left with default
433
468
 
434
- def popld(self, default: I) -> I:
435
- """Pop one item from left side of the circular array, provide
436
- a mandatory default value. "Safe" version of ``popl``.
469
+ Pop a single items off the left side of the ``CA``.
470
+
471
+ :param default: Default value to return if ``CA`` is empty.
472
+ :returns: Item popped from left side (front) of circular array
473
+ if not empty, otherwise return the provided default
474
+ value.
437
475
 
438
- :param default: Item returned if circular array is empty.
439
- :returns: Item popped from left side or default item if empty.
440
476
  """
441
477
  try:
442
478
  return self.popl()
443
479
  except ValueError:
444
480
  return default
445
481
 
446
- def poprd(self, default: I) -> I:
447
- """Pop one item from right side of the circular array, provide
448
- a mandatory default value. "Safe" version of ``popr``.
482
+ def poprd(self, default: X) -> X:
483
+ """
484
+ .. admonition:: Pop Right with default
485
+
486
+ Pop a single items off the right side of the ``CA``.
487
+
488
+ :param default: Default value to return if ``CA`` is empty.
489
+ :returns: Item popped from right side (rear) of circular array
490
+ if not empty, otherwise return the provided default
491
+ value.
449
492
 
450
- :param default: Item returned if circular array is empty.
451
- :returns: Item popped from right side or default item if empty.
452
493
  """
453
494
  try:
454
495
  return self.popr()
455
496
  except ValueError:
456
497
  return default
457
498
 
458
- def poplt(self, maximum: int) -> tuple[I, ...]:
459
- """Pop multiple items from left side of circular array.
499
+ def poplt(self, maximum: int) -> tuple[X, ...]:
500
+ """
501
+ .. admonition:: Pop multiple items from left
502
+
503
+ Pop items off the left side of the ``CA``.
504
+
505
+ :param maximum: Maximum number of items to pop, may pop less if not enough items in ``CA``.
506
+ :returns: A ``tuple`` of the items popped, left to right.
460
507
 
461
- :param maximum: Maximum number of items to pop, may pop less if not enough items.
462
- :returns: Tuple of items in the order popped, left to right.
463
508
  """
464
- item_list: list[I] = []
509
+ item_list: list[X] = []
465
510
 
466
511
  while maximum > 0:
467
512
  try:
@@ -473,13 +518,17 @@ class CA[I]:
473
518
 
474
519
  return tuple(item_list)
475
520
 
476
- def poprt(self, maximum: int) -> tuple[I, ...]:
477
- """Pop multiple items from right side of circular array.
521
+ def poprt(self, maximum: int) -> tuple[X, ...]:
522
+ """
523
+ .. admonition:: Pop multiple items from right
524
+
525
+ Pop items off the right side of the ``CA``.
526
+
527
+ :param maximum: Maximum number of items to pop, may pop less if not enough items in ``CA``.
528
+ :returns: A ``tuple`` of the items popped, right to left.
478
529
 
479
- :param maximum: Maximum number of items to pop, may pop less if not enough items.
480
- :returns: Tuple of items in the order popped, right to left.
481
530
  """
482
- item_list: list[I] = []
531
+ item_list: list[X] = []
483
532
  while maximum > 0:
484
533
  try:
485
534
  item_list.append(self.popr())
@@ -490,9 +539,14 @@ class CA[I]:
490
539
  return tuple(item_list)
491
540
 
492
541
  def rotl(self, n: int = 1) -> None:
493
- """Rotate items to the left.
542
+ """
543
+ .. admonition:: Rotate left
544
+
545
+ Rotate contents of ``CA`` to the left putting first
546
+ item onto rear.
547
+
548
+ :param n: Number of times to shift items left. Default 1 time.
494
549
 
495
- :param n: Number of times to shift elements to the left.
496
550
  """
497
551
  if self._cnt < 2:
498
552
  return
@@ -500,35 +554,48 @@ class CA[I]:
500
554
  self.pushr(self.popl())
501
555
 
502
556
  def rotr(self, n: int = 1) -> None:
503
- """Rotate items to the right.
557
+ """
558
+ .. admonition:: Rotate right
559
+
560
+ Rotate contents of ``CA`` to the right putting last
561
+ item onto front.
562
+
563
+ :param n: Number of times to shift items right. Default 1 time.
504
564
 
505
- :param n: Number of times to shift elements to the right.
506
565
  """
507
566
  if self._cnt < 2:
508
567
  return
509
568
  for _ in range(n, 0, -1):
510
569
  self.pushl(self.popr())
511
570
 
512
- def map[U](self, f: Callable[[I], U]) -> 'CA[U]':
513
- """Apply function ``f`` over the circular array's contents.
571
+ def map[Y](self, f: Callable[[X], Y]) -> 'CA[Y]':
572
+ """
573
+ .. admonition:: Map function over the CA
514
574
 
515
- :param f: Callable from type ``I`` to type ``U``.
575
+ Apply function ``f`` over the circular array's contents.
576
+
577
+ :param f: Callable from type ``X`` to type ``Y``.
516
578
  :returns: New auto-resizing circular array instance.
579
+
517
580
  """
518
581
  return CA(map(f, self))
519
582
 
520
583
  @overload
521
- def foldl[L](self, f: Callable[[I, I], I]) -> I: ...
584
+ def foldl[L](self, f: Callable[[X, X], X]) -> X: ...
522
585
  @overload
523
- def foldl[L](self, f: Callable[[L, I], L], start: L) -> L: ...
586
+ def foldl[L](self, f: Callable[[L, X], L], start: L) -> L: ...
587
+
588
+ def foldl[L](self, f: Callable[[L, X], L], start: L | NoValue = NoValue()) -> L:
589
+ """
590
+ .. admonition:: Fold left
524
591
 
525
- def foldl[L](self, f: Callable[[L, I], L], start: L | NoValue = NoValue()) -> L:
526
- """Fold left with a function and optional starting item.
592
+ Fold ``CA`` left with a function and optional starting item.
527
593
 
528
594
  :param f: Folding function, first argument to ``f`` is for the accumulator.
529
- :param start: "Optional" starting item.
595
+ :param start: Optional starting item.
530
596
  :returns: Reduced value produced by the left fold.
531
- :raises ValueError: When circular array empty and no starting item given.
597
+ :raises ValueError: When circular array empty and ``start`` not given.
598
+
532
599
  """
533
600
  if self._cnt == 0:
534
601
  if start is nada:
@@ -548,17 +615,21 @@ class CA[I]:
548
615
  return acc
549
616
 
550
617
  @overload
551
- def foldr[R](self, f: Callable[[I, I], I]) -> I: ...
618
+ def foldr[R](self, f: Callable[[X, X], X]) -> X: ...
552
619
  @overload
553
- def foldr[R](self, f: Callable[[I, R], R], start: R) -> R: ...
620
+ def foldr[R](self, f: Callable[[X, R], R], start: R) -> R: ...
621
+
622
+ def foldr[R](self, f: Callable[[X, R], R], start: R | NoValue = nada) -> R:
623
+ """
624
+ .. admonition:: Fold right
554
625
 
555
- def foldr[R](self, f: Callable[[I, R], R], start: R | NoValue = nada) -> R:
556
- """Fold right with a function and an optional starting item.
626
+ Fold ``CA`` right with a function and optional starting item.
557
627
 
558
628
  :param f: Folding function, second argument to ``f`` is for the accumulator.
559
- :param start: "Optional" starting item.
629
+ :param start: Optional starting item.
560
630
  :returns: Reduced value produced by the right fold.
561
- :raises ValueError: When circular array empty and no starting item given.
631
+ :raises ValueError: When circular array empty and ``start`` not given.
632
+
562
633
  """
563
634
  if self._cnt == 0:
564
635
  if start is nada:
@@ -578,16 +649,25 @@ class CA[I]:
578
649
  return acc
579
650
 
580
651
  def capacity(self) -> int:
581
- """Return current storage capacity of the circular array.
652
+ """
653
+ .. admonition:: Get capacity
654
+
655
+ Get the current storage capacity of the circular array.
582
656
 
583
657
  :returns: Current storage capacity.
658
+
584
659
  """
585
660
  return self._cap
586
661
 
587
662
  def empty(self) -> None:
588
- """Empty the circular array, keep current storage capacity."""
663
+ """
664
+ .. admonition:: Empty circular array
665
+
666
+ Empty the circular array, keep current storage capacity.
667
+
668
+ """
589
669
  (
590
- self._items,
670
+ self._xs,
591
671
  self._front,
592
672
  self._rear,
593
673
  self._cnt,
@@ -599,36 +679,48 @@ class CA[I]:
599
679
  )
600
680
 
601
681
  def fraction_filled(self) -> float:
602
- """Find fraction of the storage capacity which is filled.
682
+ """
683
+ .. admonition:: Get fraction filled
684
+
685
+ Find fraction of the storage capacity which is filled.
603
686
 
604
687
  :returns: The ratio count/capacity.
688
+
605
689
  """
606
690
  return self._cnt / self._cap
607
691
 
608
692
  def resize(self, minimum_capacity: int = 2) -> None:
609
- """Compact circular array and, if necessary, resize to a minimum
610
- storage capacity. To just compact the circular array, do not
611
- provide ``minimum_capacity``.
693
+ """
694
+ .. admonition:: Resize
695
+
696
+ Compact circular array and, if necessary, resize to a
697
+ minimum storage capacity. To just compact the circular
698
+ array, do not provide ``minimum_capacity``.
612
699
 
613
700
  :param minimum_capacity: Minimum storage capacity to compact the circular array.
701
+
614
702
  """
615
703
  self._compact_storage_capacity()
616
704
  if (min_cap := minimum_capacity) > self._cap:
617
705
  (
618
706
  self._cap,
619
- self._items,
707
+ self._xs,
620
708
  ) = (
621
709
  min_cap,
622
- self._items + [nada] * (min_cap - self._cap),
710
+ self._xs + [nada] * (min_cap - self._cap),
623
711
  )
624
712
  if self._cnt == 0:
625
713
  self._front, self._rear = 0, self._cap - 1
626
714
 
627
715
 
628
- def ca[T](*items: T) -> CA[T]:
629
- """Produce circular array from a variable number of arguments.
716
+ def ca[T](*ts: T) -> CA[T]:
717
+ """
718
+ .. admonition:: Circular array factory function
719
+
720
+ Produce a circular array from a variable number of arguments.
630
721
 
631
- :param items: Initial items for a new auto-resizing circular array.
722
+ :param ts: Initial items for a new auto-resizing circular array.
632
723
  :returns: New variable storage capacity circular array.
724
+
633
725
  """
634
- return CA(items)
726
+ return CA(ts)