🏠

what even is zef?

let's start with the feeling, not the definition.

You open a Python file. You write:

from zef import *

And suddenly you have ET, RT, FX, F, and a flood of unfamiliar names. You see code samples with pipes (|) everywhere. UIDs shaped like πŸƒ-97421467198ef6d64520. You stop and ask the fair question:

"…what kind of library is this?"

the one-sentence version

Zef is a python+rust library where your whole program β€” data, functions, types, and side effects β€” is a stream of plain values piped through transforms. You construct values, you pipe them, and then you | collect (for pure stuff) or | run (for effects). That's the whole rhythm.

why does it exist?

Most modern applications have a similar shape: you have data flowing in, you want to transform it, you want to persist some of it, expose some of it over HTTP, and you want the whole thing to not fall over under load.

Each of those jobs has its own library, usually. You end up gluing together FastAPI + Pydantic + Celery + Redis + Postgres + an ORM + asyncio + a serialization layer + a logger + a config system. Every glue seam is a place bugs live.

the thesis of zef

What if those aren't really different problems? What if they all become one problem the moment you treat "doing a thing" as just another value you can print, store, and compare?

Make the side effect a value, and the difference between "running an HTTP server" and "saving to a database" and "printing to the screen" disappears into the same vocabulary.

your first working zef program

Here's a complete Zef program. Read it once, then I'll unpack every line.

from zef import *

# 1. pure: pipe some data through a chain of ZefOps
result = [1, 2, 3, 4] | map(multiply(2)) | reduce(add) | collect
print(result)   # 20

# 2. effect: construct a side-effect value, run it
FX.Print(content='🌿 hello zef!') | run

Two blocks. Two kinds of thing. Let's name them.

mental model #1

Zef has two worlds:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ PURE WORLD β”‚ β”‚ EFFECTFUL WORLD β”‚ β”‚ "data & ops" β”‚ β”‚ "side effects" β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ end with: β”‚ β”‚ end with: β”‚ β”‚ | collect β”‚ β”‚ | run β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ examples: β”‚ β”‚ examples: β”‚ β”‚ map, filter, β”‚ β”‚ FX.Print, β”‚ β”‚ reduce, sort, β”‚ β”‚ FX.HTTPRequest, β”‚ β”‚ apply, ... β”‚ β”‚ FX.StartServer, β”‚ β”‚ β”‚ β”‚ FX.Publish, ... β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Same syntax (the pipe), different "end word." Keep this picture β€” we'll come back to it constantly.

what you can build

what's weirdly different?

🧊 values are bytes

Every Zef value is a contiguous chunk of memory. A Dict? Bytes. A Graph? Bytes. No pointers to stuff off elsewhere. Means you can memcpy a Zef value to a file or socket and it just works.

πŸ”€ types are sets

No static type checker needed. "Is 42 an Int?" is a plain runtime question. And you can refine any type with any predicate: Int & (Z > 18).

⚑ effects are values

FX.HTTPRequest(...) is just data. Nothing happens until you | run it. Means you can build, compare, ship, or log effects before executing.

but… why would anyone want all that?

Because when data, code, and effects look the same, you can use the same tools on all of them. One query language. One serialization. One test strategy. One mental model β€” not ten.

We're going to spend the rest of this book unpacking exactly how that plays out, chapter by chapter. Ready?

how the rest of the book flows

We go in this order:

  1. Foundations (you are here): what, why, and the | operator
  2. ZefOps: the pure computation layer
  3. Data & types: Zen notation, type-as-set, entities
  4. Graphs: the data model, updates, traversal
  5. Effects & functions: FX catalog, @zef_function
  6. State & persistence: DBs, signals
  7. Concurrency: actors, topics
  8. Servers: HTTP, WebSocket, auth
  9. Advanced: parsing, workers, a full chat agent
  10. Wrap-up: the zen of zef + a cheat sheet

take five seconds

Close your eyes. Picture two boxes: pure world (ends with | collect) and effectful world (ends with | run). That's the shape of a Zef program. When you feel lost later β€” come back to this picture.

Next up: the three big ideas that underpin everything. β†’