Skip to content

🫣 Query Peeking🔗

Queries are lazy and can only be used once (they are exhausted after being iterated). While this provides a significant performance boost, it can be inconvenient in some cases.

Peeking is a way to look at items in a query, without consuming it.

Common Use Cases🔗

Debugging🔗

When debugging a query, it is often useful to see what the next item is, without consuming the query, since consuming may change the course of the function.

from fliq import q
numbers = q([1, 2, 3, 4, 5])
# Breakpoint here: dev takes a look at the next item using `numbers.peek()`
even = numbers.where(lambda x: x % 2 == 0)  # flow continues as usual

Logging🔗

In some cases, developers may want to log a sample of the data. However, this may be needed at a point in time where the query does not need to be materialized. For such case, peeking is useful.

from fliq import q
import logging
numbers = q([1, 2, 3, 4, 5])
logging.info(f"Sample item: {numbers.peek()}")  # logging a sample item
even = numbers.where(lambda x: x % 2 == 0)  # flow continues as usual

Peeking🔗

Peeking is done using the peek method.

What makes peeking very powerful, is that you can peek a query at any point in its lifetime. Yes, even during iteration!

from fliq import q
items = q(range(5))
iterated = []
peeked = None
for i, element in enumerate(items):
    if i == 1:
        peeked = items.peek()  # 🫣 peeking during iteration!
    iterated.append(element)
assert iterated == [i for i in range(5)]
assert peeked == 2

peek()🔗

Return the first n elements of the query, without exhausting the query. If n is 1, returns the first element as a single item, otherwise returns a tuple (that can be unpacked). If n is greater than the number of elements in the query, pad will be returned for the remaining items (defaults to None). Use this to inspect the first n elements of the query, before consuming the query itself. Common use cases are logging and debugging.

Examples:

>>> from fliq import q
>>> items = q(range(10))
>>> i0, i1 = items.peek(2)
>>> i0, i1
(0, 1)
>>> items.to_list()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a, b = q([]).peek(n=2)
>>> a, b
(None, None)
Notes

Uses O(n) memory, as it materializes the first n elements. Supports infinite iterables.

Parameters:

  • n (int, default: 1 ) –

    Optional. The number of elements to peek. Defaults to 1.

  • pad (Optional[T], default: None ) –

    Optional. The value to use for padding when the query is exhausted.

Raises:

  • ValueError –

    In case n is not positive.

Returns:

  • Union[Optional[T], Sequence[Optional[T]]] –

    A tuple of the first n elements of the query. If the query has less than n elements, the other missing elements will be returned as None.