Skip to content

Release 0.6.6

Choose a tag to compare

@OutSquareCapital OutSquareCapital released this 09 Jan 20:36
· 1980 commits to master since this release

πŸš€ pyochain 0.6.6 β€” Release Notes

Date: 2026-01-09 πŸ“…

πŸ†• Highlights

  • Iter.__bool__() for lazy iteration checks β€” Check if an iterator has elements without consuming them
  • Peekable now implements Checkable β€” Peeked values now returned as Seq[T] with truthiness checking
  • Removed deprecated Iter.empty() β€” Use .new() instead
  • Improved documentation β€” Enhanced trait descriptions and interoperability examples

πŸ”„ API Changes & New Features

New: Iter.__bool__() Method

Added a __bool__() method to Iter for efficient emptiness checking without consuming elements:

>>> import pyochain as pc
>>> it = pc.Iter([1, 2, 3])
>>> bool(it)  # Check if iterator has elements
True
>>> it.collect()  # All elements still available
Seq(1, 2, 3)
>>> empty_it = pc.Iter([])
>>> bool(empty_it)
False

This method uses itertools.islice() and itertools.chain() to peek without consuming.

Checkable Methods Now Work Correctly on Iter

With __bool__() implemented, Iter now properly supports Checkable methods like .then() and .ok_or():

>>> import pyochain as pc
>>> pc.Iter([1, 2, 3]).then(lambda x: x.map(lambda v: v * 2).collect())
Some(Seq(2, 4, 6))
>>> pc.Iter([]).then(lambda x: x.map(lambda v: v * 2).collect())
NONE

Performance Consideration: Collect First When Appropriate

While __bool__() enables proper Checkable behavior on iterators, prefer collecting to a concrete collection first if Checkable methods are applied within iteration:

>>> import pyochain as pc
>>>
>>> # ❌ Less efficient: __bool__() called on each iteration in the map
>>> # This mean reconstructing the Iterator chain repeatedly
>>> result = (
...     pc.Iter([1, 2, 3])
...     .filter_map(lambda x: pc.Iter(range(x)).then_some().map(lambda s: s.sum()))
...     .collect()
... )
>>> result
Seq(0, 1, 3)
>>> # βœ… More efficient: collect first
>>> result = (
...     pc.Iter([1, 2, 3])
...     .filter_map(lambda x: pc.Iter(range(x)).collect().then_some().map(lambda s: s.sum()))
...     .collect()
... )
>>> result
Seq(0, 1, 3)

Calling __bool__() on Iter reconstructs the iterator chain, and doing this repeatedly within .map() or similar iteration operations is costly.

By collecting to eager collections (Seq, Vec, Set, etc.) beforehand, subsequent Checkable checks use __len__() which is a direct operation.

Breaking: Peekable Refactored

Peekable now inherits from Checkable and returns peeked values as Seq[T] instead of Iter[T]:

>>> import pyochain as pc
>>> data = pc.Iter([1, 2, 3]).peekable(2)
>>> data.peek  # Now returns Seq directly
Seq(1, 2)
>>> data.values.collect()  # Iter still includes peeked elements
Seq(1, 2, 3)
>>> # Checkable truthiness based on peeked values
>>> data.then_some().map(lambda d: d.peek)
Some(Seq(1, 2))

Migration: Code using .peek.collect() should be updated to use .peek directly since it's already a Seq.

Removed: Iter.empty() Deprecated Method

The deprecated Iter.empty() method has been removed. Use .new() from the PyoIterable trait instead:

>>> import pyochain as pc
>>> pc.Iter.new().collect()  # Before: pc.Iter.empty()
Seq()
>>> pc.Seq.new()  # Also works on other collections
Seq()

Questions? Report issues on our GitHub Issues page.