better-py

Pipe & Flow

Left-to-right function chaining

Piping Values

Pass a value through a sequence of functions, executing left-to-right. Each function receives the output of the previous one. Unlike compose, pipe executes immediately and returns the final value.

from better_py.functions import pipe

result = pipe(5,
    lambda x: x + 1,  # 6
    lambda x: x * 2   # 12
)

The value 5 flows through each transformation. Use pipe for one-off transformations where you don't need to reuse the pipeline.

Creating Reusable Pipelines

Create a reusable pipeline from a sequence of functions. Returns a function that, when called, executes the pipeline on the input.

from better_py.functions import flow

process = flow(
    lambda x: x + 1,
    lambda x: x * 2
)

process(5)   # 12
process(10)  # 22

Like pipe but returns a function instead of executing immediately. Use flow when you need to apply the same transformation to multiple values.

Making Functions Pipeable

Mark a function as usable in pipe operations. The pipeable decorator adds a marker that indicates the function is designed to work with pipes.

from better_py.functions import pipe, pipeable

@pipeable
def add_one(x):
    return x + 1

@pipeable
def double(x):
    return x * 2

pipe(5, add_one, double)  # 12

The decorator makes your intent clear and enables tooling to recognize pipeable functions.

Collection Pipeline

Builder interface for collection operations. Chain methods like map, filter, and reduce before executing on a collection.

from better_py.functions import Pipeline

result = (Pipeline()
    .map(lambda x: x * 2)
    .filter(lambda x: x > 0)
    .execute([1, -2, 3]))  # [2, 6]

Each method returns the Pipeline object for chaining. Call execute() with your collection to run the pipeline.

The Pipeline also supports the pipe operator (|) syntax:

from better_py.functions import Pipeline

pipeline = Pipeline().map(lambda x: x * 2)
result = pipeline | (lambda x: [i for i in x if i > 0])
# Execute with: result.execute([1, -2, 3])

Example: Data Processing

Here's a realistic data processing pipeline:

from better_py.functions import pipe

def parse(text):
    return int(text)

def validate(n):
    return n if n > 0 else None

def format(n):
    return f"Value: {n}"

result = pipe("42", parse, validate, format)

The input is parsed, validated, then formatted. Each step is isolated and testable.

Reference

FunctionPurposeReturns
pipeOne-off transformationValue
flowReusable pipelineFunction
pipeableMark function as pipeableDecorator
PipelineCollection operationsBuilder

Use pipe for single transformations, flow for reusable transformations, pipeable to mark functions designed for piping, and Pipeline for working with collections.

On this page