pythonic-fp.containers 2.0.0__py3-none-any.whl → 3.0.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/containers/__init__.py +13 -1
- pythonic_fp/containers/functional_tuple.py +56 -67
- pythonic_fp/containers/functional_tuple.pyi +58 -0
- pythonic_fp/containers/immutable_list.py +48 -56
- pythonic_fp/containers/immutable_list.pyi +72 -0
- pythonic_fp/containers/queues/__init__.py +31 -0
- pythonic_fp/containers/queues/de.py +178 -0
- pythonic_fp/containers/queues/de.pyi +45 -0
- pythonic_fp/containers/queues/fifo.py +143 -0
- pythonic_fp/containers/queues/fifo.pyi +44 -0
- pythonic_fp/containers/queues/lifo.py +134 -0
- pythonic_fp/containers/queues/lifo.pyi +40 -0
- pythonic_fp/containers/queues/py.typed +0 -0
- pythonic_fp_containers-3.0.1.dist-info/METADATA +62 -0
- pythonic_fp_containers-3.0.1.dist-info/RECORD +18 -0
- pythonic_fp/containers/box.py +0 -159
- pythonic_fp/containers/maybe.py +0 -226
- pythonic_fp/containers/xor.py +0 -314
- pythonic_fp_containers-2.0.0.dist-info/METADATA +0 -50
- pythonic_fp_containers-2.0.0.dist-info/RECORD +0 -11
- {pythonic_fp_containers-2.0.0.dist-info → pythonic_fp_containers-3.0.1.dist-info}/WHEEL +0 -0
- {pythonic_fp_containers-2.0.0.dist-info → pythonic_fp_containers-3.0.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,7 +12,19 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""
|
|
15
|
+
"""Package of container like data structures.
|
|
16
|
+
|
|
17
|
+
+------------------+--------+----------------------------------------------------+
|
|
18
|
+
| Description | Class | Package/Module |
|
|
19
|
+
+==================+========+====================================================+
|
|
20
|
+
| Functional tuple | FTuple | module ``pythonic_fp.containers.functional_tuple`` |
|
|
21
|
+
+------------------+--------+----------------------------------------------------+
|
|
22
|
+
| Immutable list | IList | module ``pythonic_fp.containers.immutable_list`` |
|
|
23
|
+
+------------------+--------+----------------------------------------------------+
|
|
24
|
+
| Queues | | package ``pythonic_fp.containers.queues`` |
|
|
25
|
+
+------------------+--------+----------------------------------------------------+
|
|
26
|
+
|
|
27
|
+
"""
|
|
16
28
|
|
|
17
29
|
__author__ = 'Geoffrey R. Scheller'
|
|
18
30
|
__copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
|
|
@@ -14,25 +14,30 @@
|
|
|
14
14
|
|
|
15
15
|
"""Pythonic FP - Functional Tuple"""
|
|
16
16
|
|
|
17
|
-
from __future__ import annotations
|
|
18
|
-
|
|
19
17
|
from collections.abc import Callable, Iterator
|
|
20
|
-
from typing import cast, Never, overload
|
|
21
|
-
from pythonic_fp.iterables import
|
|
18
|
+
from typing import cast, Never, overload, TypeVar, SupportsIndex
|
|
19
|
+
from pythonic_fp.iterables.folding import accumulate
|
|
20
|
+
from pythonic_fp.iterables.merging import blend, concat, MergeEnum
|
|
21
|
+
|
|
22
|
+
__all__ = ['FTuple']
|
|
23
|
+
|
|
24
|
+
D = TypeVar('D', covariant=True)
|
|
22
25
|
|
|
23
|
-
__all__ = ['FunctionalTuple', 'functional_tuple']
|
|
24
26
|
|
|
25
|
-
class
|
|
27
|
+
class FTuple[D](tuple[D, ...]):
|
|
26
28
|
"""Functional Tuple suitable for inheritance
|
|
27
29
|
|
|
28
30
|
- Supports both indexing and slicing
|
|
29
|
-
-
|
|
31
|
+
- FTuple addition and int multiplication supported
|
|
30
32
|
|
|
31
33
|
- addition concatenates results, resulting in a Union type
|
|
32
34
|
- both left and right int multiplication supported
|
|
33
35
|
- homogeneous in its data type
|
|
34
36
|
- supports being further inherited from
|
|
35
37
|
- unslotted
|
|
38
|
+
|
|
39
|
+
- Since these tuples are homogeneous, their covariance may be quirky
|
|
40
|
+
|
|
36
41
|
"""
|
|
37
42
|
|
|
38
43
|
def __reversed__(self) -> Iterator[D]:
|
|
@@ -54,17 +59,14 @@ class FunctionalTuple[D](tuple[D, ...]):
|
|
|
54
59
|
return False
|
|
55
60
|
return True
|
|
56
61
|
|
|
57
|
-
@overload # type:ignore
|
|
58
|
-
def __getitem__(self, x: int) -> D: ...
|
|
59
62
|
@overload
|
|
60
|
-
def __getitem__(self,
|
|
61
|
-
|
|
62
|
-
def __getitem__(self, idx:
|
|
63
|
-
def newtup(tup: tuple[D, ...]) -> tuple[D, ...]:
|
|
64
|
-
return tup[0:-1] + tup[-1:]
|
|
63
|
+
def __getitem__(self, idx: SupportsIndex) -> D: ...
|
|
64
|
+
@overload
|
|
65
|
+
def __getitem__(self, idx: slice) -> tuple[D, ...]: ...
|
|
65
66
|
|
|
67
|
+
def __getitem__(self, idx: SupportsIndex | slice) -> tuple[D, ...] | D:
|
|
66
68
|
if isinstance(idx, slice):
|
|
67
|
-
return self.__class__(
|
|
69
|
+
return self.__class__(super().__getitem__(idx))
|
|
68
70
|
else:
|
|
69
71
|
return super().__getitem__(idx)
|
|
70
72
|
|
|
@@ -80,19 +82,20 @@ class FunctionalTuple[D](tuple[D, ...]):
|
|
|
80
82
|
- fold left with an optional starting value
|
|
81
83
|
- first argument of function f is for the accumulated value
|
|
82
84
|
|
|
83
|
-
:raises ValueError: when
|
|
85
|
+
:raises ValueError: when FTuple empty and a start value not given
|
|
86
|
+
|
|
84
87
|
"""
|
|
85
|
-
|
|
88
|
+
it_self = iter(self)
|
|
86
89
|
if start is not None:
|
|
87
90
|
acc = start
|
|
88
91
|
elif self:
|
|
89
|
-
acc = cast(L, next(
|
|
92
|
+
acc = cast(L, next(it_self))
|
|
90
93
|
else:
|
|
91
94
|
if default is None:
|
|
92
|
-
msg = 'Both start and default cannot be None for an empty
|
|
93
|
-
raise ValueError('
|
|
95
|
+
msg = 'Both start and default cannot be None for an empty FTuple'
|
|
96
|
+
raise ValueError('FTuple.foldl - ' + msg)
|
|
94
97
|
acc = default
|
|
95
|
-
for v in
|
|
98
|
+
for v in it_self:
|
|
96
99
|
acc = f(acc, v)
|
|
97
100
|
return acc
|
|
98
101
|
|
|
@@ -108,82 +111,68 @@ class FunctionalTuple[D](tuple[D, ...]):
|
|
|
108
111
|
- fold right with an optional starting value
|
|
109
112
|
- second argument of function f is for the accumulated value
|
|
110
113
|
|
|
111
|
-
:raises ValueError: when
|
|
114
|
+
:raises ValueError: when FTuple empty and a start value not given
|
|
115
|
+
|
|
112
116
|
"""
|
|
113
|
-
|
|
117
|
+
it_self = reversed(self)
|
|
114
118
|
if start is not None:
|
|
115
119
|
acc = start
|
|
116
120
|
elif self:
|
|
117
|
-
acc = cast(R, next(
|
|
121
|
+
acc = cast(R, next(it_self))
|
|
118
122
|
else:
|
|
119
123
|
if default is None:
|
|
120
|
-
msg = 'Both start and default cannot be None for an empty
|
|
121
|
-
raise ValueError('
|
|
124
|
+
msg = 'Both start and default cannot be None for an empty FTuple'
|
|
125
|
+
raise ValueError('FTuple.foldR - ' + msg)
|
|
122
126
|
acc = default
|
|
123
|
-
for v in
|
|
127
|
+
for v in it_self:
|
|
124
128
|
acc = f(v, acc)
|
|
125
129
|
return acc
|
|
126
130
|
|
|
127
|
-
def copy(self) ->
|
|
128
|
-
"""Return a shallow copy of ``
|
|
131
|
+
def copy(self) -> 'FTuple[D]':
|
|
132
|
+
"""Return a shallow copy of ``FTuple`` in O(1) time & space complexity."""
|
|
129
133
|
return self.__class__(self)
|
|
130
134
|
|
|
131
135
|
def __add__(self, other: object, /) -> tuple[D, ...]:
|
|
132
|
-
if not isinstance(other,
|
|
133
|
-
msg = '
|
|
136
|
+
if not isinstance(other, tuple):
|
|
137
|
+
msg = 'FTuple being added to something not an FTuple'
|
|
134
138
|
raise ValueError(msg)
|
|
135
139
|
return self.__class__(concat(self, other))
|
|
136
140
|
|
|
137
|
-
def __mul__(self, num:
|
|
141
|
+
def __mul__(self, num: SupportsIndex) -> tuple[D, ...]:
|
|
138
142
|
return self.__class__(super().__mul__(num))
|
|
139
143
|
|
|
140
|
-
def __rmul__(self, num:
|
|
144
|
+
def __rmul__(self, num: SupportsIndex) -> tuple[D, ...]:
|
|
141
145
|
return self.__class__(super().__rmul__(num))
|
|
142
146
|
|
|
143
147
|
def accummulate[L](
|
|
144
148
|
self, f: Callable[[L, D], L], s: L | None = None, /
|
|
145
|
-
) ->
|
|
149
|
+
) -> 'FTuple[L]':
|
|
146
150
|
"""Accumulate partial folds
|
|
147
151
|
|
|
148
|
-
Accumulate partial fold results in an ``
|
|
152
|
+
Accumulate partial fold results in an ``FTuple`` with an optional
|
|
149
153
|
starting value.
|
|
154
|
+
|
|
150
155
|
"""
|
|
151
156
|
if s is None:
|
|
152
|
-
return
|
|
153
|
-
return
|
|
157
|
+
return FTuple(accumulate(self, f))
|
|
158
|
+
return FTuple(accumulate(self, f, s))
|
|
154
159
|
|
|
155
|
-
def map[U](self, f: Callable[[D], U], /) ->
|
|
156
|
-
return
|
|
160
|
+
def map[U](self, f: Callable[[D], U], /) -> 'FTuple[U]':
|
|
161
|
+
return FTuple(map(f, self))
|
|
157
162
|
|
|
158
163
|
def bind[U](
|
|
159
|
-
self,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
self,
|
|
165
|
+
f: 'Callable[[D], FTuple[U]]',
|
|
166
|
+
merge_enum: MergeEnum = MergeEnum.Concat,
|
|
167
|
+
yield_partials: bool = False,
|
|
168
|
+
) -> 'FTuple[U] | Never':
|
|
169
|
+
"""Bind function ``f`` to the ``FTuple``.
|
|
164
170
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
171
|
+
:param ds: values to instantiate FTuple
|
|
172
|
+
:return: resulting FTuple
|
|
173
|
+
:raises ValueError: if given unknown merge_type
|
|
168
174
|
|
|
169
|
-
:param ds: values to instantiate FunctionalTuple
|
|
170
|
-
:return: resulting FunctionalTuple
|
|
171
175
|
"""
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
case FM.MERGE:
|
|
176
|
-
return FunctionalTuple(merge(*map(f, self)))
|
|
177
|
-
case FM.EXHAUST:
|
|
178
|
-
return FunctionalTuple(exhaust(*map(f, self)))
|
|
179
|
-
|
|
180
|
-
raise ValueError('Unknown FM type')
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def functional_tuple[D](*ds: D):
|
|
184
|
-
"""Construct a ``FunctionalTuple`` from arguments.
|
|
185
|
-
|
|
186
|
-
:param ds: values to instantiate FunctionalTuple
|
|
187
|
-
:return: resulting FunctionalTuple
|
|
188
|
-
"""
|
|
189
|
-
return FunctionalTuple(ds)
|
|
176
|
+
return FTuple(
|
|
177
|
+
blend(*map(f, self), merge_enum=merge_enum, yield_partials=yield_partials)
|
|
178
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright 2023-2025 Geoffrey R. Scheller
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from collections.abc import Callable, Iterator
|
|
16
|
+
from typing import Never, overload, TypeVar, SupportsIndex
|
|
17
|
+
from pythonic_fp.iterables.merging import MergeEnum
|
|
18
|
+
|
|
19
|
+
__all__ = ['FTuple']
|
|
20
|
+
|
|
21
|
+
D = TypeVar('D', covariant=True)
|
|
22
|
+
|
|
23
|
+
class FTuple[D](tuple[D, ...]):
|
|
24
|
+
def __reversed__(self) -> Iterator[D]: ...
|
|
25
|
+
def __repr__(self) -> str: ...
|
|
26
|
+
def __eq__(self, other: object, /) -> bool: ...
|
|
27
|
+
@overload
|
|
28
|
+
def __getitem__(self, idx: SupportsIndex) -> D: ...
|
|
29
|
+
@overload
|
|
30
|
+
def __getitem__(self, idx: slice) -> tuple[D, ...]: ...
|
|
31
|
+
def foldl[L](
|
|
32
|
+
self,
|
|
33
|
+
f: Callable[[L, D], L],
|
|
34
|
+
/,
|
|
35
|
+
start: L | None = None,
|
|
36
|
+
default: L | None = None,
|
|
37
|
+
) -> L | None: ...
|
|
38
|
+
def foldr[R](
|
|
39
|
+
self,
|
|
40
|
+
f: Callable[[D, R], R],
|
|
41
|
+
/,
|
|
42
|
+
start: R | None = None,
|
|
43
|
+
default: R | None = None,
|
|
44
|
+
) -> R | None: ...
|
|
45
|
+
def copy(self) -> FTuple[D]: ...
|
|
46
|
+
def __add__(self, other: object, /) -> tuple[D, ...]: ...
|
|
47
|
+
def __mul__(self, num: SupportsIndex) -> tuple[D, ...]: ...
|
|
48
|
+
def __rmul__(self, num: SupportsIndex) -> tuple[D, ...]: ...
|
|
49
|
+
def accummulate[L](
|
|
50
|
+
self, f: Callable[[L, D], L], s: L | None = None, /
|
|
51
|
+
) -> FTuple[L]: ...
|
|
52
|
+
def map[U](self, f: Callable[[D], U], /) -> FTuple[U]: ...
|
|
53
|
+
def bind[U](
|
|
54
|
+
self,
|
|
55
|
+
f: Callable[[D], FTuple[U]],
|
|
56
|
+
merge_enum: MergeEnum = MergeEnum.Concat,
|
|
57
|
+
yield_partials: bool = False,
|
|
58
|
+
) -> FTuple[U] | Never: ...
|
|
@@ -18,23 +18,23 @@
|
|
|
18
18
|
- declared covariant in its generic datatype
|
|
19
19
|
- hashability should be enforced by LSP tooling
|
|
20
20
|
- hashability will be enforced at runtime
|
|
21
|
-
-
|
|
22
|
-
-
|
|
21
|
+
- IList addition supported via concatenation
|
|
22
|
+
- IList integer multiplication supported
|
|
23
23
|
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
-
from __future__ import annotations
|
|
27
|
-
|
|
28
26
|
from collections.abc import Callable, Iterable, Iterator, Hashable
|
|
29
27
|
from typing import cast, Never, overload, TypeVar
|
|
30
|
-
from pythonic_fp.iterables import
|
|
28
|
+
from pythonic_fp.iterables.folding import accumulate
|
|
29
|
+
from pythonic_fp.iterables.merging import blend, concat, MergeEnum
|
|
31
30
|
|
|
32
|
-
__all__ = ['
|
|
31
|
+
__all__ = ['IList']
|
|
33
32
|
|
|
34
33
|
D = TypeVar('D', covariant=True)
|
|
35
34
|
T = TypeVar('T')
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
|
|
37
|
+
class IList[D](Hashable):
|
|
38
38
|
"""Immutable List like data structure.
|
|
39
39
|
|
|
40
40
|
- its method type parameters are also covariant
|
|
@@ -42,6 +42,7 @@ class ImmutableList[D](Hashable):
|
|
|
42
42
|
- supports both indexing and slicing
|
|
43
43
|
- addition concatenates results, resulting type a Union type
|
|
44
44
|
- both left and right int multiplication supported
|
|
45
|
+
|
|
45
46
|
"""
|
|
46
47
|
|
|
47
48
|
__slots__ = ('_ds', '_len', '_hash')
|
|
@@ -53,7 +54,7 @@ class ImmutableList[D](Hashable):
|
|
|
53
54
|
|
|
54
55
|
def __init__(self, *dss: Iterable[D]) -> None:
|
|
55
56
|
if (size := len(dss)) > 1:
|
|
56
|
-
msg = f'
|
|
57
|
+
msg = f'IList expects at most 1 iterable argument, got {size}'
|
|
57
58
|
raise ValueError(msg)
|
|
58
59
|
else:
|
|
59
60
|
self._ds: tuple[D, ...] = tuple(dss[0]) if size == 1 else tuple()
|
|
@@ -61,7 +62,7 @@ class ImmutableList[D](Hashable):
|
|
|
61
62
|
try:
|
|
62
63
|
self._hash = hash((self._len, 42) + self._ds)
|
|
63
64
|
except TypeError as exc:
|
|
64
|
-
msg = f'
|
|
65
|
+
msg = f'IList: {exc}'
|
|
65
66
|
raise TypeError(msg)
|
|
66
67
|
|
|
67
68
|
def __hash__(self) -> int:
|
|
@@ -86,7 +87,7 @@ class ImmutableList[D](Hashable):
|
|
|
86
87
|
return '((' + ', '.join(map(repr, self)) + '))'
|
|
87
88
|
|
|
88
89
|
def __eq__(self, other: object, /) -> bool:
|
|
89
|
-
if not isinstance(other,
|
|
90
|
+
if not isinstance(other, IList):
|
|
90
91
|
return NotImplemented # magic object
|
|
91
92
|
if self._len != other._len:
|
|
92
93
|
return False
|
|
@@ -97,11 +98,11 @@ class ImmutableList[D](Hashable):
|
|
|
97
98
|
@overload
|
|
98
99
|
def __getitem__(self, idx: int, /) -> D: ...
|
|
99
100
|
@overload
|
|
100
|
-
def __getitem__(self, idx: slice, /) ->
|
|
101
|
+
def __getitem__(self, idx: slice, /) -> 'IList[D]': ...
|
|
101
102
|
|
|
102
|
-
def __getitem__(self, idx: slice | int, /) ->
|
|
103
|
+
def __getitem__(self, idx: slice | int, /) -> 'IList[D] | D':
|
|
103
104
|
if isinstance(idx, slice):
|
|
104
|
-
return
|
|
105
|
+
return IList(self._ds[idx])
|
|
105
106
|
return self._ds[idx]
|
|
106
107
|
|
|
107
108
|
def foldl[L](
|
|
@@ -115,8 +116,9 @@ class ImmutableList[D](Hashable):
|
|
|
115
116
|
|
|
116
117
|
- fold left with an optional starting value
|
|
117
118
|
- first argument of function ``f`` is for the accumulated value
|
|
118
|
-
|
|
119
|
+
|
|
119
120
|
"raises ValueError: when empty and a start value not given
|
|
121
|
+
|
|
120
122
|
"""
|
|
121
123
|
it = iter(self._ds)
|
|
122
124
|
if start is not None:
|
|
@@ -125,9 +127,9 @@ class ImmutableList[D](Hashable):
|
|
|
125
127
|
acc = cast(L, next(it)) # L_co = D_co in this case
|
|
126
128
|
else:
|
|
127
129
|
if default is None:
|
|
128
|
-
msg0 = '
|
|
130
|
+
msg0 = 'IList: foldl method requires '
|
|
129
131
|
msg1 = 'either start or default to be defined for '
|
|
130
|
-
msg2 = 'an empty
|
|
132
|
+
msg2 = 'an empty IList'
|
|
131
133
|
raise ValueError(msg0 + msg1 + msg2)
|
|
132
134
|
acc = default
|
|
133
135
|
for v in it:
|
|
@@ -147,6 +149,7 @@ class ImmutableList[D](Hashable):
|
|
|
147
149
|
- second argument of function ``f`` is for the accumulated value
|
|
148
150
|
|
|
149
151
|
"raises ValueError: when empty and a start value not given
|
|
152
|
+
|
|
150
153
|
"""
|
|
151
154
|
it = reversed(self._ds)
|
|
152
155
|
if start is not None:
|
|
@@ -155,68 +158,57 @@ class ImmutableList[D](Hashable):
|
|
|
155
158
|
acc = cast(R, next(it))
|
|
156
159
|
else:
|
|
157
160
|
if default is None:
|
|
158
|
-
msg0 = '
|
|
161
|
+
msg0 = 'IList: foldr method requires '
|
|
159
162
|
msg1 = 'either start or default to be defined for '
|
|
160
|
-
msg2 = 'an empty
|
|
163
|
+
msg2 = 'an empty IList'
|
|
161
164
|
raise ValueError(msg0 + msg1 + msg2)
|
|
162
165
|
acc = default
|
|
163
166
|
for v in it:
|
|
164
167
|
acc = f(v, acc)
|
|
165
168
|
return acc
|
|
166
169
|
|
|
167
|
-
def __add__(self, other:
|
|
168
|
-
if not isinstance(other,
|
|
169
|
-
msg = '
|
|
170
|
+
def __add__(self, other: 'IList[D]', /) -> 'IList[D]':
|
|
171
|
+
if not isinstance(other, IList):
|
|
172
|
+
msg = 'IList being added to something not a IList'
|
|
170
173
|
raise ValueError(msg)
|
|
171
174
|
|
|
172
|
-
return
|
|
175
|
+
return IList(concat(self, other))
|
|
173
176
|
|
|
174
|
-
def __mul__(self, num: int, /) ->
|
|
175
|
-
return
|
|
177
|
+
def __mul__(self, num: int, /) -> 'IList[D]':
|
|
178
|
+
return IList(self._ds.__mul__(num if num > 0 else 0))
|
|
176
179
|
|
|
177
|
-
def __rmul__(self, num: int, /) ->
|
|
178
|
-
return
|
|
180
|
+
def __rmul__(self, num: int, /) -> 'IList[D]':
|
|
181
|
+
return IList(self._ds.__mul__(num if num > 0 else 0))
|
|
179
182
|
|
|
180
183
|
def accummulate[L](
|
|
181
184
|
self, f: Callable[[L, D], L], s: L | None = None, /
|
|
182
|
-
) ->
|
|
185
|
+
) -> 'IList[L]':
|
|
183
186
|
"""Accumulate partial folds
|
|
184
187
|
|
|
185
|
-
Accumulate partial fold results in an
|
|
188
|
+
Accumulate partial fold results in an IList with
|
|
186
189
|
an optional starting value.
|
|
190
|
+
|
|
187
191
|
"""
|
|
188
192
|
if s is None:
|
|
189
|
-
return
|
|
190
|
-
return
|
|
193
|
+
return IList(accumulate(self, f))
|
|
194
|
+
return IList(accumulate(self, f, s))
|
|
191
195
|
|
|
192
|
-
def map[U](self, f: Callable[[D], U], /) ->
|
|
193
|
-
return
|
|
196
|
+
def map[U](self, f: Callable[[D], U], /) -> 'IList[U]':
|
|
197
|
+
return IList(map(f, self))
|
|
194
198
|
|
|
195
199
|
def bind[U](
|
|
196
|
-
self,
|
|
197
|
-
|
|
198
|
-
|
|
200
|
+
self,
|
|
201
|
+
f: 'Callable[[D], IList[U]]',
|
|
202
|
+
merge_enum: MergeEnum = MergeEnum.Concat,
|
|
203
|
+
yield_partials: bool = False,
|
|
204
|
+
) -> 'IList[U] | Never':
|
|
205
|
+
"""Bind function `f` to the `IList`.
|
|
199
206
|
|
|
200
|
-
|
|
207
|
+
:param ds: values to instantiate IList
|
|
208
|
+
:return: resulting IList
|
|
209
|
+
:raises ValueError: if given unknown merge_type
|
|
201
210
|
|
|
202
|
-
- CONCAT: sequentially concatenate iterables one after the other
|
|
203
|
-
- MERGE: round-robin merge iterables until one is exhausted
|
|
204
|
-
- EXHAUST: round-robin merge iterables until all are exhausted
|
|
205
211
|
"""
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
case FM.MERGE:
|
|
210
|
-
return ImmutableList(merge(*map(f, self)))
|
|
211
|
-
case FM.EXHAUST:
|
|
212
|
-
return ImmutableList(exhaust(*map(f, self)))
|
|
213
|
-
|
|
214
|
-
raise ValueError(f'ImmutableList: Unknown FM type: {type}')
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
def immutable_list[T](*ts: T) -> ImmutableList[TabError]:
|
|
218
|
-
"""Function to produce an ``ImmutableList`` from a variable number of arguments.
|
|
219
|
-
|
|
220
|
-
:param ds: initial values to push onto a new ImmutableList from right to left
|
|
221
|
-
"""
|
|
222
|
-
return ImmutableList(ts)
|
|
212
|
+
return IList(
|
|
213
|
+
blend(*map(f, self), merge_enum=merge_enum, yield_partials=yield_partials)
|
|
214
|
+
)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright 2023-2025 Geoffrey R. Scheller
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from collections.abc import Callable, Iterable, Iterator, Hashable
|
|
16
|
+
from typing import Never, overload, TypeVar
|
|
17
|
+
from pythonic_fp.iterables.merging import MergeEnum
|
|
18
|
+
|
|
19
|
+
__all__ = ['IList']
|
|
20
|
+
|
|
21
|
+
D = TypeVar('D', covariant=True)
|
|
22
|
+
T = TypeVar('T')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class IList[D](Hashable):
|
|
26
|
+
__slots__ = ('_ds', '_len', '_hash')
|
|
27
|
+
__match_args__ = ('_ds', '_len')
|
|
28
|
+
|
|
29
|
+
L = TypeVar('L')
|
|
30
|
+
R = TypeVar('R')
|
|
31
|
+
U = TypeVar('U')
|
|
32
|
+
|
|
33
|
+
def __init__(self, *dss: Iterable[D]) -> None: ...
|
|
34
|
+
def __hash__(self) -> int: ...
|
|
35
|
+
def __iter__(self) -> Iterator[D]: ...
|
|
36
|
+
def __reversed__(self) -> Iterator[D]: ...
|
|
37
|
+
def __bool__(self) -> bool: ...
|
|
38
|
+
def __len__(self) -> int: ...
|
|
39
|
+
def __repr__(self) -> str: ...
|
|
40
|
+
def __str__(self) -> str: ...
|
|
41
|
+
def __eq__(self, other: object, /) -> bool: ...
|
|
42
|
+
@overload
|
|
43
|
+
def __getitem__(self, idx: int, /) -> D: ...
|
|
44
|
+
@overload
|
|
45
|
+
def __getitem__(self, idx: slice, /) -> IList[D]: ...
|
|
46
|
+
def foldl[L](
|
|
47
|
+
self,
|
|
48
|
+
f: Callable[[L, D], L],
|
|
49
|
+
/,
|
|
50
|
+
start: L | None = None,
|
|
51
|
+
default: L | None = None,
|
|
52
|
+
) -> L | None: ...
|
|
53
|
+
def foldr[R](
|
|
54
|
+
self,
|
|
55
|
+
f: Callable[[D, R], R],
|
|
56
|
+
/,
|
|
57
|
+
start: R | None = None,
|
|
58
|
+
default: R | None = None,
|
|
59
|
+
) -> R | None: ...
|
|
60
|
+
def __add__(self, other: IList[D], /) -> IList[D]: ...
|
|
61
|
+
def __mul__(self, num: int, /) -> IList[D]: ...
|
|
62
|
+
def __rmul__(self, num: int, /) -> IList[D]: ...
|
|
63
|
+
def accummulate[L](
|
|
64
|
+
self, f: Callable[[L, D], L], s: L | None = None, /
|
|
65
|
+
) -> IList[L]: ...
|
|
66
|
+
def map[U](self, f: Callable[[D], U], /) -> IList[U]: ...
|
|
67
|
+
def bind[U](
|
|
68
|
+
self,
|
|
69
|
+
f: Callable[[D], IList[U]],
|
|
70
|
+
merge_enum: MergeEnum = MergeEnum.Concat,
|
|
71
|
+
yield_partials: bool = False,
|
|
72
|
+
) -> IList[U] | Never: ...
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Copyright 2023-2024 Geoffrey R. Scheller
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Three types of queues.
|
|
16
|
+
|
|
17
|
+
+------------------------------------+-----------+--------------------------+
|
|
18
|
+
| module | Class | description |
|
|
19
|
+
+====================================+===========+==========================+
|
|
20
|
+
| pythonic_fp.containers.queues.fifo | FIFOQueue | First-In-First-Out queue |
|
|
21
|
+
+------------------------------------+-----------+--------------------------+
|
|
22
|
+
| pythonic_fp.containers.queues.lifo | LIFOQueue | Last-In-First-Out queue |
|
|
23
|
+
+------------------------------------+-----------+--------------------------+
|
|
24
|
+
| pythonic_fp.containers.queues.de | DEQueue | Double-Ended queue |
|
|
25
|
+
+------------------------------------+-----------+--------------------------+
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__author__ = 'Geoffrey R. Scheller'
|
|
30
|
+
__copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
|
|
31
|
+
__license__ = 'Apache License 2.0'
|