pythonic-fp-circulararray 6.0.4__py3-none-any.whl → 6.1.1__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.
- pythonic_fp/circulararray/__init__.py +6 -8
- pythonic_fp/circulararray/auto.py +236 -133
- pythonic_fp/circulararray/auto.pyi +3 -3
- pythonic_fp/circulararray/fixed.py +240 -138
- pythonic_fp/circulararray/fixed.pyi +5 -5
- {pythonic_fp_circulararray-6.0.4.dist-info → pythonic_fp_circulararray-6.1.1.dist-info}/METADATA +6 -6
- pythonic_fp_circulararray-6.1.1.dist-info/RECORD +11 -0
- pythonic_fp_circulararray-6.0.4.dist-info/RECORD +0 -11
- {pythonic_fp_circulararray-6.0.4.dist-info → pythonic_fp_circulararray-6.1.1.dist-info}/WHEEL +0 -0
- {pythonic_fp_circulararray-6.0.4.dist-info → pythonic_fp_circulararray-6.1.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,19 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""
|
|
16
|
-
.. admonition:: Fixed storage capacity circular array CAF
|
|
17
|
-
|
|
18
|
-
- O(1) pops and pushes either end
|
|
19
|
-
- O(1) indexing, does not support slicing
|
|
20
|
-
- fixed total storage capacity
|
|
21
|
-
- iterable, safely mutates while iterators iterating over previous state
|
|
22
|
-
- comparisons compare identity before equality, like builtins
|
|
23
|
-
- in boolean context, falsy when either empty or full, otherwise truthy
|
|
24
|
-
- function ``caf`` produces fixed capacity circular array from arguments
|
|
25
|
-
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
15
|
from collections.abc import Callable, Iterable, Iterator
|
|
29
16
|
from typing import cast, Final, overload
|
|
30
17
|
from pythonic_fp.gadgets.sentinels.novalue import NoValue
|
|
@@ -35,19 +22,38 @@ nada: Final[NoValue] = NoValue()
|
|
|
35
22
|
|
|
36
23
|
|
|
37
24
|
class CAF[X]:
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
.. admonition:: Fixed storage capacity circular array CAF
|
|
28
|
+
|
|
29
|
+
- O(1) pops and pushes either end
|
|
30
|
+
- O(1) indexing, does not support slicing
|
|
31
|
+
- fixed total storage capacity
|
|
32
|
+
- iterable but not threadsafe
|
|
33
|
+
- comparisons compare identity before equality, like builtins
|
|
34
|
+
- in boolean context, falsy when either empty or full,
|
|
35
|
+
otherwise truthy
|
|
36
|
+
- function ``caf`` produces fixed capacity circular array
|
|
37
|
+
from arguments
|
|
38
|
+
|
|
39
|
+
"""
|
|
38
40
|
__slots__ = '_xs', '_cnt', '_cap', '_front', '_rear'
|
|
39
41
|
|
|
40
42
|
def __init__(self, *xs: Iterable[X], cap: int = 2) -> None:
|
|
41
43
|
"""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
.. admonition:: initializer
|
|
45
|
+
|
|
46
|
+
Populate ``CAF`` with an optional iterable
|
|
47
|
+
from front (left) to rear (right).
|
|
48
|
+
|
|
49
|
+
:param xs: Takes 0 or 1 iterable parameters.
|
|
50
|
+
:raises ValueError: When more than one parameter is provided.
|
|
51
|
+
:raises TypeError: When passed a non-iterable parameter.
|
|
46
52
|
|
|
47
53
|
"""
|
|
48
54
|
cap = max(2, cap)
|
|
49
55
|
if (size := len(xs)) > 1:
|
|
50
|
-
msg = f'CAF expects at most 1
|
|
56
|
+
msg = f'CAF expects at most 1 iterable, got {size}'
|
|
51
57
|
raise ValueError(msg)
|
|
52
58
|
if size:
|
|
53
59
|
values: list[X | NoValue] = list(cast(Iterable[X | NoValue], xs[0]))
|
|
@@ -66,7 +72,96 @@ class CAF[X]:
|
|
|
66
72
|
self._front = 0
|
|
67
73
|
self._rear = cnt - 1
|
|
68
74
|
|
|
75
|
+
def __bool__(self) -> bool:
|
|
76
|
+
"""
|
|
77
|
+
.. admonition:: bool
|
|
78
|
+
|
|
79
|
+
- falsy if either empty or full
|
|
80
|
+
- truthy otherwise
|
|
81
|
+
|
|
82
|
+
:returns: ``True`` when partially filled,
|
|
83
|
+
``False`` otherwise.
|
|
84
|
+
|
|
85
|
+
"""
|
|
86
|
+
return 0 < self._cnt < self._cap
|
|
87
|
+
|
|
88
|
+
def __len__(self) -> int:
|
|
89
|
+
"""
|
|
90
|
+
.. admonition:: length
|
|
91
|
+
|
|
92
|
+
Number of items in the ``CAF``.
|
|
93
|
+
|
|
94
|
+
:returns: The number of items in the ``CAF``.
|
|
95
|
+
|
|
96
|
+
"""
|
|
97
|
+
return self._cnt
|
|
98
|
+
|
|
99
|
+
def __eq__(self, other: object) -> bool:
|
|
100
|
+
"""
|
|
101
|
+
.. admonition:: equality comparison
|
|
102
|
+
|
|
103
|
+
Efficiently compare ``CAF`` to another object.
|
|
104
|
+
|
|
105
|
+
:param other: The object to be compared.
|
|
106
|
+
:returns: ``True`` if ``other`` is another ``CAF`` whose
|
|
107
|
+
contents compare as equal to the corresponding
|
|
108
|
+
contents of the ``CAF``, otherwise ``False``.
|
|
109
|
+
|
|
110
|
+
"""
|
|
111
|
+
if self is other:
|
|
112
|
+
return True
|
|
113
|
+
if not isinstance(other, type(self)):
|
|
114
|
+
return False
|
|
115
|
+
|
|
116
|
+
(
|
|
117
|
+
front1,
|
|
118
|
+
cnt1,
|
|
119
|
+
cap1,
|
|
120
|
+
front2,
|
|
121
|
+
cnt2,
|
|
122
|
+
cap2,
|
|
123
|
+
) = (
|
|
124
|
+
self._front,
|
|
125
|
+
self._cnt,
|
|
126
|
+
self._cap,
|
|
127
|
+
other._front,
|
|
128
|
+
other._cnt,
|
|
129
|
+
other._cap,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
if cnt1 != cnt2:
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
for nn in range(cnt1):
|
|
136
|
+
if (
|
|
137
|
+
self._xs[(front1 + nn) % cap1]
|
|
138
|
+
is other._xs[(front2 + nn) % cap2]
|
|
139
|
+
):
|
|
140
|
+
continue
|
|
141
|
+
if (
|
|
142
|
+
self._xs[(front1 + nn) % cap1]
|
|
143
|
+
!= other._xs[(front2 + nn) % cap2]
|
|
144
|
+
):
|
|
145
|
+
return False
|
|
146
|
+
return True
|
|
147
|
+
|
|
69
148
|
def __iter__(self) -> Iterator[X]:
|
|
149
|
+
"""
|
|
150
|
+
.. admonition:: iterate
|
|
151
|
+
|
|
152
|
+
Iterates circular array, front (left) to rear (right).
|
|
153
|
+
|
|
154
|
+
.. warning
|
|
155
|
+
|
|
156
|
+
Not thread safe, especially for long living iterators.
|
|
157
|
+
|
|
158
|
+
.. tip::
|
|
159
|
+
|
|
160
|
+
Cache contents to make more thread tolerant. Put
|
|
161
|
+
a lock around circular array during caching process
|
|
162
|
+
to make threadsafe.
|
|
163
|
+
|
|
164
|
+
"""
|
|
70
165
|
if self._cnt > 0:
|
|
71
166
|
(
|
|
72
167
|
cap,
|
|
@@ -86,6 +181,22 @@ class CAF[X]:
|
|
|
86
181
|
yield cast(X, current_state[position])
|
|
87
182
|
|
|
88
183
|
def __reversed__(self) -> Iterator[X]:
|
|
184
|
+
"""
|
|
185
|
+
.. admonition:: reverse iterate
|
|
186
|
+
|
|
187
|
+
Iterates circular array, rear (right) to front (left).
|
|
188
|
+
|
|
189
|
+
.. warning
|
|
190
|
+
|
|
191
|
+
Not thread safe, especially for long living iterators.
|
|
192
|
+
|
|
193
|
+
.. tip::
|
|
194
|
+
|
|
195
|
+
Cache contents to make more thread tolerant. Put
|
|
196
|
+
a lock around circular array during caching process
|
|
197
|
+
to make threadsafe.
|
|
198
|
+
|
|
199
|
+
"""
|
|
89
200
|
if self._cnt > 0:
|
|
90
201
|
(
|
|
91
202
|
cap,
|
|
@@ -104,27 +215,14 @@ class CAF[X]:
|
|
|
104
215
|
position = (position - 1) % cap
|
|
105
216
|
yield cast(X, current_state[position])
|
|
106
217
|
|
|
107
|
-
def
|
|
218
|
+
def __getitem__(self, idx: int) -> X:
|
|
108
219
|
"""
|
|
109
|
-
|
|
220
|
+
.. admonition:: getitem
|
|
110
221
|
|
|
111
|
-
|
|
112
|
-
|
|
222
|
+
Fixed capacity circular arrays are indexable but
|
|
223
|
+
not sliceable.
|
|
113
224
|
|
|
114
|
-
def __str__(self) -> str:
|
|
115
225
|
"""
|
|
116
|
-
:returns: String of the form ``(|x1, x2, ..., xn|)``.
|
|
117
|
-
|
|
118
|
-
"""
|
|
119
|
-
return '(|' + ', '.join(map(str, self)) + '|)'
|
|
120
|
-
|
|
121
|
-
def __bool__(self) -> bool:
|
|
122
|
-
return 0 < self._cnt < self._cap
|
|
123
|
-
|
|
124
|
-
def __len__(self) -> int:
|
|
125
|
-
return self._cnt
|
|
126
|
-
|
|
127
|
-
def __getitem__(self, idx: int) -> X:
|
|
128
226
|
cnt = self._cnt
|
|
129
227
|
if 0 <= idx < cnt:
|
|
130
228
|
return cast(X, self._xs[(self._front + idx) % self._cap])
|
|
@@ -142,6 +240,13 @@ class CAF[X]:
|
|
|
142
240
|
raise IndexError(msg1 + msg2 + msg3)
|
|
143
241
|
|
|
144
242
|
def __setitem__(self, idx: int, val: X) -> None:
|
|
243
|
+
"""
|
|
244
|
+
.. admonition:: setitem
|
|
245
|
+
|
|
246
|
+
Fixed capacity circular arrays are indexable but
|
|
247
|
+
not sliceable.
|
|
248
|
+
|
|
249
|
+
"""
|
|
145
250
|
cnt = self._cnt
|
|
146
251
|
if 0 <= idx < cnt:
|
|
147
252
|
self._xs[(self._front + idx) % self._cap] = val
|
|
@@ -157,6 +262,13 @@ class CAF[X]:
|
|
|
157
262
|
raise IndexError(msg1 + msg2 + msg3)
|
|
158
263
|
|
|
159
264
|
def __delitem__(self, idx: int) -> None:
|
|
265
|
+
"""
|
|
266
|
+
.. admonition:: delitem
|
|
267
|
+
|
|
268
|
+
Fixed capacity circular arrays are indexable but
|
|
269
|
+
not sliceable.
|
|
270
|
+
|
|
271
|
+
"""
|
|
160
272
|
item_list = list(self)
|
|
161
273
|
del item_list[idx]
|
|
162
274
|
_ca = CAF(item_list, cap = self._cap)
|
|
@@ -173,59 +285,39 @@ class CAF[X]:
|
|
|
173
285
|
)
|
|
174
286
|
del _ca
|
|
175
287
|
|
|
176
|
-
def
|
|
288
|
+
def __repr__(self) -> str:
|
|
177
289
|
"""
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
290
|
+
.. admonition:: repr string
|
|
291
|
+
|
|
292
|
+
Construct string 'CAF(x₁, x₂, … xₙ)' where
|
|
293
|
+
x₁, x₂, … xₙ are the contents displayed with ``repr()``.
|
|
294
|
+
|
|
295
|
+
:returns: A string to reproduce the ``CAF``.
|
|
182
296
|
|
|
183
297
|
"""
|
|
184
|
-
|
|
185
|
-
return True
|
|
186
|
-
if not isinstance(other, type(self)):
|
|
187
|
-
return False
|
|
298
|
+
return 'caf(' + ', '.join(map(repr, self)) + ')'
|
|
188
299
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
cnt2,
|
|
195
|
-
cap2,
|
|
196
|
-
) = (
|
|
197
|
-
self._front,
|
|
198
|
-
self._cnt,
|
|
199
|
-
self._cap,
|
|
200
|
-
other._front,
|
|
201
|
-
other._cnt,
|
|
202
|
-
other._cap,
|
|
203
|
-
)
|
|
300
|
+
def __str__(self) -> str:
|
|
301
|
+
r"""
|
|
302
|
+
.. admonition:: user string
|
|
303
|
+
Construct string '(\|x₁, x₂, … xₙ\|)' where
|
|
304
|
+
x₁, x₂, ..., xₙ are the contents displayed with ``str()``.
|
|
204
305
|
|
|
205
|
-
|
|
206
|
-
return False
|
|
306
|
+
:returns: A string meaningful to an end user.
|
|
207
307
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
self._xs[(front1 + nn) % cap1]
|
|
211
|
-
is other._xs[(front2 + nn) % cap2]
|
|
212
|
-
):
|
|
213
|
-
continue
|
|
214
|
-
if (
|
|
215
|
-
self._xs[(front1 + nn) % cap1]
|
|
216
|
-
!= other._xs[(front2 + nn) % cap2]
|
|
217
|
-
):
|
|
218
|
-
return False
|
|
219
|
-
return True
|
|
308
|
+
"""
|
|
309
|
+
return '(|' + ', '.join(map(str, self)) + '|)'
|
|
220
310
|
|
|
221
|
-
def pushl(self,
|
|
311
|
+
def pushl(self, x: X) -> None:
|
|
222
312
|
"""
|
|
223
|
-
.. admonition::
|
|
313
|
+
.. admonition:: push left
|
|
224
314
|
|
|
225
315
|
Push single item from the left onto the ``CAF``.
|
|
226
316
|
|
|
227
|
-
|
|
228
|
-
|
|
317
|
+
:param x: Single item to be pushed onto the front of
|
|
318
|
+
the ``CAF`` from the left.
|
|
319
|
+
:raises ValueError: When called on a full fixed storage
|
|
320
|
+
capacity circular array.
|
|
229
321
|
|
|
230
322
|
"""
|
|
231
323
|
if self._cnt == self._cap:
|
|
@@ -238,18 +330,20 @@ class CAF[X]:
|
|
|
238
330
|
self._cnt,
|
|
239
331
|
) = (
|
|
240
332
|
(self._front - 1) % self._cap,
|
|
241
|
-
|
|
333
|
+
x,
|
|
242
334
|
self._cnt + 1,
|
|
243
335
|
)
|
|
244
336
|
|
|
245
|
-
def pushr(self,
|
|
337
|
+
def pushr(self, x: X) -> None:
|
|
246
338
|
"""
|
|
247
|
-
.. admonition::
|
|
339
|
+
.. admonition:: push right
|
|
248
340
|
|
|
249
341
|
Push single item from the right onto the ``CAF``.
|
|
250
342
|
|
|
251
|
-
|
|
252
|
-
|
|
343
|
+
:param x: Single item to be pushed onto the rear of
|
|
344
|
+
the ``CAF`` from the right.
|
|
345
|
+
:raises ValueError: When called on a full fixed
|
|
346
|
+
storage capacity circular array.
|
|
253
347
|
|
|
254
348
|
"""
|
|
255
349
|
if self._cnt == self._cap:
|
|
@@ -262,23 +356,23 @@ class CAF[X]:
|
|
|
262
356
|
self._cnt,
|
|
263
357
|
) = (
|
|
264
358
|
(self._rear + 1) % self._cap,
|
|
265
|
-
|
|
359
|
+
x,
|
|
266
360
|
self._cnt + 1,
|
|
267
361
|
)
|
|
268
362
|
|
|
269
363
|
def popl(self) -> X:
|
|
270
364
|
"""
|
|
271
|
-
.. admonition::
|
|
365
|
+
.. admonition:: pop left
|
|
272
366
|
|
|
273
367
|
Pop a single items off the left side of the ``CAF``.
|
|
274
368
|
|
|
275
|
-
|
|
276
|
-
|
|
369
|
+
:returns: Item popped from left side (front) of the ``CAF``.
|
|
370
|
+
:raises ValueError: When called on an empty ``CAF``.
|
|
277
371
|
|
|
278
372
|
"""
|
|
279
373
|
if self._cnt > 1:
|
|
280
374
|
(
|
|
281
|
-
|
|
375
|
+
x,
|
|
282
376
|
self._xs[self._front],
|
|
283
377
|
self._front,
|
|
284
378
|
self._cnt,
|
|
@@ -290,7 +384,7 @@ class CAF[X]:
|
|
|
290
384
|
)
|
|
291
385
|
elif self._cnt == 1:
|
|
292
386
|
(
|
|
293
|
-
|
|
387
|
+
x,
|
|
294
388
|
self._xs[self._front],
|
|
295
389
|
self._cnt,
|
|
296
390
|
self._front,
|
|
@@ -305,21 +399,21 @@ class CAF[X]:
|
|
|
305
399
|
else:
|
|
306
400
|
msg = 'Method popl called on an empty CAF'
|
|
307
401
|
raise ValueError(msg)
|
|
308
|
-
return cast(X,
|
|
402
|
+
return cast(X, x)
|
|
309
403
|
|
|
310
404
|
def popr(self) -> X:
|
|
311
405
|
"""
|
|
312
|
-
.. admonition::
|
|
406
|
+
.. admonition:: pop right
|
|
313
407
|
|
|
314
408
|
Pop a single items off the right side of the ``CAF``.
|
|
315
409
|
|
|
316
|
-
|
|
317
|
-
|
|
410
|
+
:returns: Item popped from right side (rear) of the ``CAF``.
|
|
411
|
+
:raises ValueError: When called on an empty ``CAF``.
|
|
318
412
|
|
|
319
413
|
"""
|
|
320
414
|
if self._cnt > 1:
|
|
321
415
|
(
|
|
322
|
-
|
|
416
|
+
x,
|
|
323
417
|
self._xs[self._rear],
|
|
324
418
|
self._rear,
|
|
325
419
|
self._cnt,
|
|
@@ -331,7 +425,7 @@ class CAF[X]:
|
|
|
331
425
|
)
|
|
332
426
|
elif self._cnt == 1:
|
|
333
427
|
(
|
|
334
|
-
|
|
428
|
+
x,
|
|
335
429
|
self._xs[self._front],
|
|
336
430
|
self._cnt,
|
|
337
431
|
self._front,
|
|
@@ -346,18 +440,18 @@ class CAF[X]:
|
|
|
346
440
|
else:
|
|
347
441
|
msg = 'Method popr called on an empty CAF'
|
|
348
442
|
raise ValueError(msg)
|
|
349
|
-
return cast(X,
|
|
443
|
+
return cast(X, x)
|
|
350
444
|
|
|
351
445
|
def popld(self, default: X) -> X:
|
|
352
446
|
"""
|
|
353
|
-
.. admonition::
|
|
447
|
+
.. admonition:: pop Left with default
|
|
354
448
|
|
|
355
449
|
Pop a single items off the left side of the ``CAF``.
|
|
356
450
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
451
|
+
:param default: Default value to return if ``CAF`` is empty.
|
|
452
|
+
:returns: Item popped from left side (front) of the ``CAF``
|
|
453
|
+
if not empty, otherwise return the provided
|
|
454
|
+
default value.
|
|
361
455
|
|
|
362
456
|
"""
|
|
363
457
|
try:
|
|
@@ -367,14 +461,14 @@ class CAF[X]:
|
|
|
367
461
|
|
|
368
462
|
def poprd(self, default: X) -> X:
|
|
369
463
|
"""
|
|
370
|
-
.. admonition::
|
|
464
|
+
.. admonition:: pop Right with default
|
|
371
465
|
|
|
372
466
|
Pop a single items off the right side of the ``CAF``.
|
|
373
467
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
468
|
+
:param default: Default value to return if ``CAF`` is empty.
|
|
469
|
+
:returns: Item popped from right side (rear) of the ``CAF``
|
|
470
|
+
if not empty, otherwise return the provided
|
|
471
|
+
default value.
|
|
378
472
|
|
|
379
473
|
"""
|
|
380
474
|
try:
|
|
@@ -388,21 +482,22 @@ class CAF[X]:
|
|
|
388
482
|
|
|
389
483
|
Pop items off the left side of the ``CAF``.
|
|
390
484
|
|
|
391
|
-
|
|
392
|
-
|
|
485
|
+
:param maximum: Maximum number of items to pop,
|
|
486
|
+
may pop less if not enough items in ``CAF``.
|
|
487
|
+
:returns: A ``tuple`` of the items popped, left to right.
|
|
393
488
|
|
|
394
489
|
"""
|
|
395
|
-
|
|
490
|
+
xs: list[X] = []
|
|
396
491
|
|
|
397
492
|
while maximum > 0:
|
|
398
493
|
try:
|
|
399
|
-
|
|
494
|
+
xs.append(self.popl())
|
|
400
495
|
except ValueError:
|
|
401
496
|
break
|
|
402
497
|
else:
|
|
403
498
|
maximum -= 1
|
|
404
499
|
|
|
405
|
-
return tuple(
|
|
500
|
+
return tuple(xs)
|
|
406
501
|
|
|
407
502
|
def poprt(self, maximum: int) -> tuple[X, ...]:
|
|
408
503
|
"""
|
|
@@ -410,19 +505,20 @@ class CAF[X]:
|
|
|
410
505
|
|
|
411
506
|
Pop items off the right side of the ``CAF``.
|
|
412
507
|
|
|
413
|
-
|
|
414
|
-
|
|
508
|
+
:param maximum: Maximum number of items to pop,
|
|
509
|
+
may pop less if not enough items in ``CAF``.
|
|
510
|
+
:returns: A ``tuple`` of the items popped, right to left.
|
|
415
511
|
|
|
416
512
|
"""
|
|
417
|
-
|
|
513
|
+
xs: list[X] = []
|
|
418
514
|
while maximum > 0:
|
|
419
515
|
try:
|
|
420
|
-
|
|
516
|
+
xs.append(self.popr())
|
|
421
517
|
except ValueError:
|
|
422
518
|
break
|
|
423
519
|
else:
|
|
424
520
|
maximum -= 1
|
|
425
|
-
return tuple(
|
|
521
|
+
return tuple(xs)
|
|
426
522
|
|
|
427
523
|
def rotl(self, n: int = 1) -> None:
|
|
428
524
|
"""
|
|
@@ -431,7 +527,8 @@ class CAF[X]:
|
|
|
431
527
|
Rotate contents of ``CAF`` to the left putting first
|
|
432
528
|
item onto rear.
|
|
433
529
|
|
|
434
|
-
|
|
530
|
+
:param n: Number of times to shift items left.
|
|
531
|
+
Default 1 time.
|
|
435
532
|
|
|
436
533
|
"""
|
|
437
534
|
if self._cnt < 2:
|
|
@@ -446,7 +543,8 @@ class CAF[X]:
|
|
|
446
543
|
Rotate contents of ``CAF`` to the right putting last
|
|
447
544
|
item onto front.
|
|
448
545
|
|
|
449
|
-
|
|
546
|
+
:param n: Number of times to shift items right.
|
|
547
|
+
Default 1 time.
|
|
450
548
|
|
|
451
549
|
"""
|
|
452
550
|
if self._cnt < 2:
|
|
@@ -460,8 +558,8 @@ class CAF[X]:
|
|
|
460
558
|
|
|
461
559
|
Apply function ``f`` over the circular array's contents.
|
|
462
560
|
|
|
463
|
-
|
|
464
|
-
|
|
561
|
+
:param f: Callable from type ``X`` to type ``Y``.
|
|
562
|
+
:returns: New fixed capacity circular array instance.
|
|
465
563
|
|
|
466
564
|
"""
|
|
467
565
|
return CAF(map(f, self), cap = self._cap)
|
|
@@ -477,10 +575,12 @@ class CAF[X]:
|
|
|
477
575
|
|
|
478
576
|
Fold ``CAF`` left with a function and optional starting item.
|
|
479
577
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
578
|
+
:param f: Folding function, first argument to ``f`` is for
|
|
579
|
+
the accumulator.
|
|
580
|
+
:param start: Optional starting item.
|
|
581
|
+
:returns: Reduced value produced by the left fold.
|
|
582
|
+
:raises ValueError: When circular array empty and ``start``
|
|
583
|
+
not given.
|
|
484
584
|
|
|
485
585
|
"""
|
|
486
586
|
if self._cnt == 0:
|
|
@@ -496,8 +596,8 @@ class CAF[X]:
|
|
|
496
596
|
return acc
|
|
497
597
|
|
|
498
598
|
acc = cast(L, start)
|
|
499
|
-
for
|
|
500
|
-
acc = f(acc,
|
|
599
|
+
for x in self:
|
|
600
|
+
acc = f(acc, x)
|
|
501
601
|
return acc
|
|
502
602
|
|
|
503
603
|
@overload
|
|
@@ -511,10 +611,12 @@ class CAF[X]:
|
|
|
511
611
|
|
|
512
612
|
Fold ``CAF`` right left with a function and optional starting item.
|
|
513
613
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
614
|
+
:param f: Folding function, second argument to ``f`` is for
|
|
615
|
+
the accumulator.
|
|
616
|
+
:param start: Optional starting item.
|
|
617
|
+
:returns: Reduced value produced by the right fold.
|
|
618
|
+
:raises ValueError: When circular array empty and ``start``
|
|
619
|
+
not given.
|
|
518
620
|
|
|
519
621
|
"""
|
|
520
622
|
if self._cnt == 0:
|
|
@@ -530,8 +632,8 @@ class CAF[X]:
|
|
|
530
632
|
return acc
|
|
531
633
|
|
|
532
634
|
acc = cast(R, start)
|
|
533
|
-
for
|
|
534
|
-
acc = f(
|
|
635
|
+
for x in reversed(self):
|
|
636
|
+
acc = f(x, acc)
|
|
535
637
|
return acc
|
|
536
638
|
|
|
537
639
|
def capacity(self) -> int:
|
|
@@ -540,8 +642,7 @@ class CAF[X]:
|
|
|
540
642
|
|
|
541
643
|
Get the fixed storage capacity of the circular array.
|
|
542
644
|
|
|
543
|
-
|
|
544
|
-
:returns: Fixed storage capacity.
|
|
645
|
+
:returns: Fixed storage capacity.
|
|
545
646
|
|
|
546
647
|
"""
|
|
547
648
|
return self._cap
|
|
@@ -571,7 +672,7 @@ class CAF[X]:
|
|
|
571
672
|
|
|
572
673
|
Find fraction of the storage capacity which is filled.
|
|
573
674
|
|
|
574
|
-
|
|
675
|
+
:returns: The ratio count/capacity.
|
|
575
676
|
|
|
576
677
|
"""
|
|
577
678
|
return self._cnt / self._cap
|
|
@@ -581,11 +682,12 @@ def caf[T](*ts: T, cap: int = 2) -> CAF[T]:
|
|
|
581
682
|
"""
|
|
582
683
|
.. admonition:: Circular array factory function
|
|
583
684
|
|
|
584
|
-
Produce a circular array from
|
|
685
|
+
Produce a fixed capacity circular array from
|
|
686
|
+
a variable number of arguments.
|
|
585
687
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
688
|
+
:param ts: Initial items for a new fixed capacity circular array.
|
|
689
|
+
:param cap: The minimum storage capacity to set.
|
|
690
|
+
:returns: New fixed storage capacity circular array.
|
|
589
691
|
|
|
590
692
|
"""
|
|
591
693
|
return CAF(ts, cap=cap)
|
|
@@ -5,16 +5,16 @@ __all__ = ['CAF', 'caf']
|
|
|
5
5
|
|
|
6
6
|
class CAF[X]:
|
|
7
7
|
def __init__(self, *xs: Iterable[X], cap: int = 2) -> None: ...
|
|
8
|
-
def __iter__(self) -> Iterator[X]: ...
|
|
9
|
-
def __reversed__(self) -> Iterator[X]: ...
|
|
10
8
|
def __bool__(self) -> bool: ...
|
|
11
9
|
def __len__(self) -> int: ...
|
|
10
|
+
def __eq__(self, other: object) -> bool: ...
|
|
11
|
+
def __iter__(self) -> Iterator[X]: ...
|
|
12
|
+
def __reversed__(self) -> Iterator[X]: ...
|
|
12
13
|
def __getitem__(self, idx: int) -> X: ...
|
|
13
14
|
def __setitem__(self, idx: int, val: X) -> None: ...
|
|
14
15
|
def __delitem__(self, idx: int) -> None: ...
|
|
15
|
-
def
|
|
16
|
-
def
|
|
17
|
-
def pushr(self, item: X) -> None: ...
|
|
16
|
+
def pushl(self, x: X) -> None: ...
|
|
17
|
+
def pushr(self, x: X) -> None: ...
|
|
18
18
|
def popl(self) -> X: ...
|
|
19
19
|
def popr(self) -> X: ...
|
|
20
20
|
def popld(self, default: X) -> X: ...
|