Skip to content

PyoMutableSequence

Bases: PyoSequence[T], MutableSequence[T], ABC


              flowchart TD
              pyochain.abc._sequences.PyoMutableSequence[PyoMutableSequence]
              pyochain.abc._sequences.PyoSequence[PyoSequence]
              pyochain.abc._collection.PyoCollection[PyoCollection]
              pyochain.abc._iterable.PyoIterable[PyoIterable]
              pyochain.rs.Pipeable[Pipeable]
              pyochain.rs.Into[Into]
              pyochain.rs.Inspect[Inspect]
              pyochain.rs.Checkable[Checkable]
              pyochain.abc._collection.PyoContainer[PyoContainer]
              pyochain.abc._collection.PyoSized[PyoSized]
              pyochain.abc._sequences.PyoReversible[PyoReversible]

                              pyochain.abc._sequences.PyoSequence --> pyochain.abc._sequences.PyoMutableSequence
                                pyochain.abc._collection.PyoCollection --> pyochain.abc._sequences.PyoSequence
                                pyochain.abc._iterable.PyoIterable --> pyochain.abc._collection.PyoCollection
                                pyochain.rs.Pipeable --> pyochain.abc._iterable.PyoIterable
                                pyochain.rs.Into --> pyochain.rs.Pipeable
                
                pyochain.rs.Inspect --> pyochain.rs.Pipeable
                

                pyochain.rs.Checkable --> pyochain.abc._iterable.PyoIterable
                

                pyochain.abc._collection.PyoContainer --> pyochain.abc._collection.PyoCollection
                
                pyochain.abc._collection.PyoSized --> pyochain.abc._collection.PyoCollection
                

                pyochain.abc._sequences.PyoReversible --> pyochain.abc._sequences.PyoSequence
                



              click pyochain.abc._sequences.PyoMutableSequence href "" "pyochain.abc._sequences.PyoMutableSequence"
              click pyochain.abc._sequences.PyoSequence href "" "pyochain.abc._sequences.PyoSequence"
              click pyochain.abc._collection.PyoCollection href "" "pyochain.abc._collection.PyoCollection"
              click pyochain.abc._iterable.PyoIterable href "" "pyochain.abc._iterable.PyoIterable"
              click pyochain.rs.Pipeable href "" "pyochain.rs.Pipeable"
              click pyochain.rs.Into href "" "pyochain.rs.Into"
              click pyochain.rs.Inspect href "" "pyochain.rs.Inspect"
              click pyochain.rs.Checkable href "" "pyochain.rs.Checkable"
              click pyochain.abc._collection.PyoContainer href "" "pyochain.abc._collection.PyoContainer"
              click pyochain.abc._collection.PyoSized href "" "pyochain.abc._collection.PyoSized"
              click pyochain.abc._sequences.PyoReversible href "" "pyochain.abc._sequences.PyoReversible"
            

Extends PyoSequence[T] and collections.abc.MutableSequence[T].

This ABC is the base class for mutable sequence types in pyochain, such as Vec.

Any concrete subclass must implement the required MutableSequence dunder methods:

  • __getitem__
  • __setitem__
  • __delitem__
  • __len__
  • insert

This class notably provides various methods inspired from Rust's Vec type, which provides memory-efficient in-place operations.

They are slower than simple .extend(), slices and clear() calls, but avoids all intermediate allocations, making them suitable for large collections where memory usage is a concern.

Source code in src/pyochain/abc/_sequences.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
class PyoMutableSequence[T](PyoSequence[T], MutableSequence[T], ABC):
    """Extends `PyoSequence[T]` and `collections.abc.MutableSequence[T]`.

    This ABC is the base class for mutable sequence types in pyochain, such as `Vec`.

    Any concrete subclass must implement the required `MutableSequence` dunder methods:

    - `__getitem__`
    - `__setitem__`
    - `__delitem__`
    - `__len__`
    - `insert`

    This class notably provides various methods inspired from Rust's `Vec` type, which provides memory-efficient in-place operations.

    They are slower than simple `.extend()`, slices and `clear()` calls, but avoids all intermediate allocations, making them suitable for large collections where memory usage is a concern.
    """

    # pyrefly: ignore [implicit-any-attribute]
    __slots__ = ()  # pyright: ignore[reportUnannotatedClassAttribute]

    def retain(self, predicate: Callable[[T], bool]) -> None:
        """Retains only the elements specified by the *predicate*.

        In other words, remove all elements for which the *predicate* function returns `False`.

        This is similar to filtering, but operates in place, visiting each element exactly once in forward order.

        Compared to `.iter().filter(predicate).collect()`, this avoids creating a new collection.

        The order of the retained elements is preserved.

        Args:
            predicate (Callable[[T], bool]): A function that returns `True` for elements to keep and `False` for elements to remove.

        Example:
            ```python
            >>> from pyochain import Vec, Seq
            >>> vec = Vec((1, 2, 3, 4))
            >>> vec.retain(lambda x: x % 2 == 0)
            >>> vec
            Vec(2, 4)

            ```
            External state may be used to decide which elements to keep.

            ```python
            >>> vec = Vec((1, 2, 3, 4, 5))
            >>> keep = Seq((False, True, True, False, True)).iter()
            >>> vec.retain(lambda _: next(keep))
            >>> vec
            Vec(2, 3, 5)

            ```
        """
        return tls.retain(self, predicate)

    def truncate(self, length: int) -> None:
        """Shortens the `MutableSequence`, keeping the first *length* elements and dropping the rest.

        If *length* is greater or equal to the `MutableSequence` current `__len__()`, this has no effect.

        `Vec::drain` can emulate `Vec::truncate`, but causes the excess elements to be returned instead of dropped.

        This is equivalent to `del seq[length:]`.

        Args:
            length (int): The length to truncate the `MutableSequence` to.

        Example:
            ```python
            >>> from pyochain import Vec
            >>> # Truncating a five element vector to two elements:
            >>> vec = Vec((1, 2, 3, 4, 5))
            >>> vec.truncate(2)
            >>> vec
            Vec(1, 2)

            ```
            No truncation occurs when len is greater than the `MutableSequence` current length:
            ```python
            >>> from pyochain import Vec
            >>> vec = Vec((1, 2, 3))
            >>> vec.truncate(8)
            >>> vec
            Vec(1, 2, 3)

            ```
            Truncating when len == 0 is equivalent to calling the clear method.
            ```python
            >>> from pyochain import Vec
            >>> vec = Vec((1, 2, 3))
            >>> vec.truncate(0)
            >>> vec
            Vec()

            ```
        """
        del self[length:]

    def extract_if(
        self, predicate: Callable[[T], bool], start: int = 0, end: int | None = None
    ) -> Iter[T]:
        """Creates an `Iter` which uses a *predicate* to determine if an element in `Self` should be removed.

        If the *predicate* returns `True`, the element is removed from `Self` and yielded.

        If the *predicate* returns `False`, the element remains in `Self` and will not be yielded.

        You can specify a range for the extraction.

        If the returned `Iterator` is not exhausted, e.g. because it is dropped without iterating or the iteration short-circuits, then the remaining elements will be retained.

        Args:
            predicate (Callable[[T], bool]): A function that takes an element and returns `True` if it should be extracted, or `False` if it should be retained.
            start (int): The starting index of the range to consider for extraction. Defaults to `0`.
            end (int | None): The ending index of the range to consider for extraction. Defaults to `None`, which means the end of `Self`.

        Returns:
            Iter[T]: An `Iter` that yields the extracted elements.

        Example:
            ```python
            >>> from pyochain import Vec
            >>> data = (1, 2, 3, 4, 5)
            >>> vec = Vec(data)
            >>> extracted = vec.extract_if(lambda x: x % 2 == 0).collect()
            >>> extracted
            Seq(2, 4)
            >>> vec
            Vec(1, 3, 5)
            >>> # Extracting with a range
            >>> vec = Vec(data)
            >>> extracted = vec.extract_if(
            ...     lambda x: x % 2 == 0, start=1, end=4
            ... ).collect()
            >>> extracted
            Seq(2, 4)
            >>> vec
            Vec(1, 3, 5)

            ```
        """
        from .._iter import Iter

        return Iter(tls.ExtractIf(self, predicate, start, end))

    def drain(self, start: int | None = None, end: int | None = None) -> Iter[T]:
        """Removes the subslice indicated by the given *start* and *end* from the `Vec`, returning an `Iterator` over the removed subslice.

        If the `Iterator` is dropped before being fully consumed, it drops the remaining removed elements.

        Args:
            start (int | None): Starting index of the subslice to drain. Defaults to `0` if `None`.
            end (int | None): Ending index of the subslice to drain. Defaults to `len(self)` if `None`.

        Returns:
            Iter[T]: An `Iterator` over the drained elements.

        Example:
            ```python
            >>> from pyochain import Vec
            >>> v = Vec.from_ref([1, 2, 3])
            >>> u = v.drain(1).collect()
            >>> v
            Vec(1)
            >>> u
            Seq(2, 3)

            ```
            Fully consuming the `Iterator` removes all drained elements
            ```python
            >>> from pyochain import Vec
            >>> v = Vec.from_ref([1, 2, 3])
            >>> _ = v.drain().collect()
            >>> v
            Vec()

            ```
            Deleting the `Iterator` will also remove all drained elements.
            ```python
            >>> from pyochain import Vec
            >>> vec = Vec.from_ref([1, 2, 3])
            >>> iterator = vec.drain()
            >>> del iterator
            >>> vec
            Vec()

            ```
        """
        from .._iter import Iter

        return Iter(tls.Drain(self, start, end))

drain(start=None, end=None)

Removes the subslice indicated by the given start and end from the Vec, returning an Iterator over the removed subslice.

If the Iterator is dropped before being fully consumed, it drops the remaining removed elements.

Parameters:

Name Type Description Default
start int | None

Starting index of the subslice to drain. Defaults to 0 if None.

None
end int | None

Ending index of the subslice to drain. Defaults to len(self) if None.

None

Returns:

Type Description
Iter[T]

Iter[T]: An Iterator over the drained elements.

Example

>>> from pyochain import Vec
>>> v = Vec.from_ref([1, 2, 3])
>>> u = v.drain(1).collect()
>>> v
Vec(1)
>>> u
Seq(2, 3)
Fully consuming the Iterator removes all drained elements
>>> from pyochain import Vec
>>> v = Vec.from_ref([1, 2, 3])
>>> _ = v.drain().collect()
>>> v
Vec()
Deleting the Iterator will also remove all drained elements.
>>> from pyochain import Vec
>>> vec = Vec.from_ref([1, 2, 3])
>>> iterator = vec.drain()
>>> del iterator
>>> vec
Vec()

Source code in src/pyochain/abc/_sequences.py
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
def drain(self, start: int | None = None, end: int | None = None) -> Iter[T]:
    """Removes the subslice indicated by the given *start* and *end* from the `Vec`, returning an `Iterator` over the removed subslice.

    If the `Iterator` is dropped before being fully consumed, it drops the remaining removed elements.

    Args:
        start (int | None): Starting index of the subslice to drain. Defaults to `0` if `None`.
        end (int | None): Ending index of the subslice to drain. Defaults to `len(self)` if `None`.

    Returns:
        Iter[T]: An `Iterator` over the drained elements.

    Example:
        ```python
        >>> from pyochain import Vec
        >>> v = Vec.from_ref([1, 2, 3])
        >>> u = v.drain(1).collect()
        >>> v
        Vec(1)
        >>> u
        Seq(2, 3)

        ```
        Fully consuming the `Iterator` removes all drained elements
        ```python
        >>> from pyochain import Vec
        >>> v = Vec.from_ref([1, 2, 3])
        >>> _ = v.drain().collect()
        >>> v
        Vec()

        ```
        Deleting the `Iterator` will also remove all drained elements.
        ```python
        >>> from pyochain import Vec
        >>> vec = Vec.from_ref([1, 2, 3])
        >>> iterator = vec.drain()
        >>> del iterator
        >>> vec
        Vec()

        ```
    """
    from .._iter import Iter

    return Iter(tls.Drain(self, start, end))

extract_if(predicate, start=0, end=None)

Creates an Iter which uses a predicate to determine if an element in Self should be removed.

If the predicate returns True, the element is removed from Self and yielded.

If the predicate returns False, the element remains in Self and will not be yielded.

You can specify a range for the extraction.

If the returned Iterator is not exhausted, e.g. because it is dropped without iterating or the iteration short-circuits, then the remaining elements will be retained.

Parameters:

Name Type Description Default
predicate Callable[[T], bool]

A function that takes an element and returns True if it should be extracted, or False if it should be retained.

required
start int

The starting index of the range to consider for extraction. Defaults to 0.

0
end int | None

The ending index of the range to consider for extraction. Defaults to None, which means the end of Self.

None

Returns:

Type Description
Iter[T]

Iter[T]: An Iter that yields the extracted elements.

Example
>>> from pyochain import Vec
>>> data = (1, 2, 3, 4, 5)
>>> vec = Vec(data)
>>> extracted = vec.extract_if(lambda x: x % 2 == 0).collect()
>>> extracted
Seq(2, 4)
>>> vec
Vec(1, 3, 5)
>>> # Extracting with a range
>>> vec = Vec(data)
>>> extracted = vec.extract_if(
...     lambda x: x % 2 == 0, start=1, end=4
... ).collect()
>>> extracted
Seq(2, 4)
>>> vec
Vec(1, 3, 5)
Source code in src/pyochain/abc/_sequences.py
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
def extract_if(
    self, predicate: Callable[[T], bool], start: int = 0, end: int | None = None
) -> Iter[T]:
    """Creates an `Iter` which uses a *predicate* to determine if an element in `Self` should be removed.

    If the *predicate* returns `True`, the element is removed from `Self` and yielded.

    If the *predicate* returns `False`, the element remains in `Self` and will not be yielded.

    You can specify a range for the extraction.

    If the returned `Iterator` is not exhausted, e.g. because it is dropped without iterating or the iteration short-circuits, then the remaining elements will be retained.

    Args:
        predicate (Callable[[T], bool]): A function that takes an element and returns `True` if it should be extracted, or `False` if it should be retained.
        start (int): The starting index of the range to consider for extraction. Defaults to `0`.
        end (int | None): The ending index of the range to consider for extraction. Defaults to `None`, which means the end of `Self`.

    Returns:
        Iter[T]: An `Iter` that yields the extracted elements.

    Example:
        ```python
        >>> from pyochain import Vec
        >>> data = (1, 2, 3, 4, 5)
        >>> vec = Vec(data)
        >>> extracted = vec.extract_if(lambda x: x % 2 == 0).collect()
        >>> extracted
        Seq(2, 4)
        >>> vec
        Vec(1, 3, 5)
        >>> # Extracting with a range
        >>> vec = Vec(data)
        >>> extracted = vec.extract_if(
        ...     lambda x: x % 2 == 0, start=1, end=4
        ... ).collect()
        >>> extracted
        Seq(2, 4)
        >>> vec
        Vec(1, 3, 5)

        ```
    """
    from .._iter import Iter

    return Iter(tls.ExtractIf(self, predicate, start, end))

retain(predicate)

Retains only the elements specified by the predicate.

In other words, remove all elements for which the predicate function returns False.

This is similar to filtering, but operates in place, visiting each element exactly once in forward order.

Compared to .iter().filter(predicate).collect(), this avoids creating a new collection.

The order of the retained elements is preserved.

Parameters:

Name Type Description Default
predicate Callable[[T], bool]

A function that returns True for elements to keep and False for elements to remove.

required
Example

>>> from pyochain import Vec, Seq
>>> vec = Vec((1, 2, 3, 4))
>>> vec.retain(lambda x: x % 2 == 0)
>>> vec
Vec(2, 4)
External state may be used to decide which elements to keep.

>>> vec = Vec((1, 2, 3, 4, 5))
>>> keep = Seq((False, True, True, False, True)).iter()
>>> vec.retain(lambda _: next(keep))
>>> vec
Vec(2, 3, 5)
Source code in src/pyochain/abc/_sequences.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
def retain(self, predicate: Callable[[T], bool]) -> None:
    """Retains only the elements specified by the *predicate*.

    In other words, remove all elements for which the *predicate* function returns `False`.

    This is similar to filtering, but operates in place, visiting each element exactly once in forward order.

    Compared to `.iter().filter(predicate).collect()`, this avoids creating a new collection.

    The order of the retained elements is preserved.

    Args:
        predicate (Callable[[T], bool]): A function that returns `True` for elements to keep and `False` for elements to remove.

    Example:
        ```python
        >>> from pyochain import Vec, Seq
        >>> vec = Vec((1, 2, 3, 4))
        >>> vec.retain(lambda x: x % 2 == 0)
        >>> vec
        Vec(2, 4)

        ```
        External state may be used to decide which elements to keep.

        ```python
        >>> vec = Vec((1, 2, 3, 4, 5))
        >>> keep = Seq((False, True, True, False, True)).iter()
        >>> vec.retain(lambda _: next(keep))
        >>> vec
        Vec(2, 3, 5)

        ```
    """
    return tls.retain(self, predicate)

truncate(length)

Shortens the MutableSequence, keeping the first length elements and dropping the rest.

If length is greater or equal to the MutableSequence current __len__(), this has no effect.

Vec::drain can emulate Vec::truncate, but causes the excess elements to be returned instead of dropped.

This is equivalent to del seq[length:].

Parameters:

Name Type Description Default
length int

The length to truncate the MutableSequence to.

required
Example

>>> from pyochain import Vec
>>> # Truncating a five element vector to two elements:
>>> vec = Vec((1, 2, 3, 4, 5))
>>> vec.truncate(2)
>>> vec
Vec(1, 2)
No truncation occurs when len is greater than the MutableSequence current length:
>>> from pyochain import Vec
>>> vec = Vec((1, 2, 3))
>>> vec.truncate(8)
>>> vec
Vec(1, 2, 3)
Truncating when len == 0 is equivalent to calling the clear method.
>>> from pyochain import Vec
>>> vec = Vec((1, 2, 3))
>>> vec.truncate(0)
>>> vec
Vec()

Source code in src/pyochain/abc/_sequences.py
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
def truncate(self, length: int) -> None:
    """Shortens the `MutableSequence`, keeping the first *length* elements and dropping the rest.

    If *length* is greater or equal to the `MutableSequence` current `__len__()`, this has no effect.

    `Vec::drain` can emulate `Vec::truncate`, but causes the excess elements to be returned instead of dropped.

    This is equivalent to `del seq[length:]`.

    Args:
        length (int): The length to truncate the `MutableSequence` to.

    Example:
        ```python
        >>> from pyochain import Vec
        >>> # Truncating a five element vector to two elements:
        >>> vec = Vec((1, 2, 3, 4, 5))
        >>> vec.truncate(2)
        >>> vec
        Vec(1, 2)

        ```
        No truncation occurs when len is greater than the `MutableSequence` current length:
        ```python
        >>> from pyochain import Vec
        >>> vec = Vec((1, 2, 3))
        >>> vec.truncate(8)
        >>> vec
        Vec(1, 2, 3)

        ```
        Truncating when len == 0 is equivalent to calling the clear method.
        ```python
        >>> from pyochain import Vec
        >>> vec = Vec((1, 2, 3))
        >>> vec.truncate(0)
        >>> vec
        Vec()

        ```
    """
    del self[length:]