Skip to content

Relationship to Klor

KlorPy is a Python port of the ideas behind Klor: Choreographies in Clojure, by Lovro Lugović and Sung-Shik Jongmans (Heart of Clojure 2024, funded by NGI Assure/NLnet).

Shared ideas

The conceptual core is the same:

Idea Klor (Clojure) KlorPy (Python)
Choreographic programming an EDSL: write one global program, project to per-role programs the same, via @choreography
Location type system agreement / tuple / chor types _UNIVERSAL / frozenset / tuple
Special operators lifting, copy, narrow, move, pack, unpack, agree! lift, copy, narrow, move, pack, unpack
Knowledge of choice a role appears in a branch only if it is part of the guard's agreement universal guards decide locally; subset guards broadcast
Erasure play-role takes only the parameters that mention a role Choreography.bind_param / role_holds_param
Runtime play-role + role config {role, send, recv, locators}; simulate-chor play_role + the same config shape; simulate_chor
TCP transport klor.sockets (java.nio + Nippy) klorpy.sockets (asyncio + pickle)

The simulate_chor/play_role API shape, the role-config transport contract, the NOOP sentinel, and the location lattice are deliberate mirrors of Klor — so the mental model transfers directly.

What had to change (no macros in Python)

  • The compiler front end. Clojure gives Klor reader macros and tools.analyzer.jvm; defchor type-checks and projects at macroexpansion. Python has neither, so @choreography parses the function's source (inspect + ast), runs the same analysis/typecheck/projection passes, and compiles per-role async closures instead of per-role source.
  • Control flow is real Python. if, match, while, break, continue are the native statements (with a match extension for case). Klor's functional style (recur) maps to the while construct here.
  • The transport is Python's async ecosystem. asyncio gives us the simulator (one task per role + in-memory queues) and the TCP transport for free.

Deliberate differences

  • No agree! yet and no defchor forward declarations — documented in the roadmap; both are future conveniences.
  • More permissive choice. Klor restricts branch participation to the guard's agreement set statically. KlorPy instead broadcasts the decision to any participating role, which is more permissive (and lets the same choreography style handle single-role guards).
  • No mypy plugin for the type checker (explained in the roadmap).
  • Scope honesty. KlorPy is a documented prototype (~1,100 lines of Python
  • 47 tests), not a production system. The limitations page is the contract.

Learning Klor through KlorPy

If you want to understand Klor's papers (the book-length treatment of choreographies is the best entry point), KlorPy is a readable, runnable companion: the location model, projection, erasure, and transport all exist in ~1,100 lines of Python with no external dependencies.