Tutorial: build a small data workflow

Tutorial: build a small data workflow#

This tutorial applies Expression to a familiar task: turn a list of raw records into a small report. It assumes you have read Getting started.

The important habit is to keep each transformation small, named, and independently testable. pipe then makes the order of those transformations obvious.

from expression import pipe
from expression.collections import seq

orders = [
    {"customer": "Ada", "amount": 12, "paid": True},
    {"customer": "Grace", "amount": 8, "paid": False},
    {"customer": "Ada", "amount": 5, "paid": True},
]


def is_paid(order: dict[str, object]) -> bool:
    return order["paid"] is True


def amount(order: dict[str, object]) -> int:
    return int(order["amount"])


revenue = pipe(
    orders,
    seq.filter(is_paid),
    seq.map(amount),
    seq.sum,
)

assert revenue == 17

Keep domain decisions in normal functions#

Expression does not replace ordinary Python. A function is often the clearest place for branching and a domain rule; a pipeline connects those functions.

from expression import compose


paid_amounts = compose(
    seq.filter(is_paid),
    seq.map(amount),
    list,
)

assert paid_amounts(orders) == [12, 5]

Next, learn how collections keep transformations lazy or immutable, and how Option and Result make incomplete workflows explicit.