Build collections with comprehensions
A comprehension produces a new collection from an iterable and optional filters. The element expression runs only after the filters pass.
def main() -> Result[(), AllocError | IoError | ZeroDivisionError | OverflowError[i64]]:
squares = [n * n for n in range(8) if n % 2 == 0]?
print(squares)?
print({n: n * n for n in [2, 3]?}?)?
print(len({n // 2 for n in range(8)}?))?
print([x * 10 + y for x in range(3) for y in range(x)]?)?
Ok(())
[0, 4, 16, 36]
{2: 4, 3: 9}
4
[10, 20, 21]
Multiple clauses nest from left to right. Later iterables can use earlier
variables, and you can use multiple if filters. Variables remain local to
the comprehension. Parenthesize a conditional expression used as an iterable
or filter. Dictionary comprehensions evaluate each key before its value.
% is modulo: the result follows the divisor’s sign, so -7 % 3 is 2.
Both operands must have the same integer type.
Every element must have the same type; there is no implicit numeric widening:
def main() -> Result[(), AllocError | IoError]:
values = [1, True]?
Ok(())
expected list[i64]
A comprehension over a range or list with no if clause reserves its full
length once; with a filter or another source it grows the output in place. The
? handles allocation failure. A comprehension with one for clause compiles
to the same loop as the equivalent pipeline.
Collect a snapshot with unpacking
Unpacking works in comprehensions too. This one collects dictionary items into a list of tuples:
def main() -> Result[(), AllocError | IoError | OverflowError[i64]]:
mut counts = {"apple": 2, "pear": 3}?
for fruit, count in (&mut counts).items():
*count = *count + 1
print([(*fruit, *count) for fruit, count in counts.items()]?)?
print([a + b for a, b in [(1, 2), (3, 4)]?]?)?
Ok(())
[("apple", 3), ("pear", 4)]
[3, 7]
For dictionaries containing owned values, use copy(value)? when the snapshot
needs independent owners.
Shared item views yield references for every key and value, so the * above
reads each copyable value before storing it in the snapshot tuple.
Text comprehensions collect Unicode scalars:
def main() -> Result[(), AllocError | IoError]:
print([character for character in "hé"]?)?
Ok(())
["h", "é"]