Axon for Python Developers
If you are coming from Python, you already understand Axon’s purpose: let AI models write efficient native code without fighting the language. Axon takes the runtime model Python programmers love (dynamic, REPL-friendly, batteries-included) and replaces the slow interpreter with a static, AI-native compiler.
The Performance Gap
Section titled “The Performance Gap”Python is the de facto language of AI/ML. Its dynamic semantics and rich ecosystem make it the fastest path from idea to prototype. But every hot loop eventually hits the GIL, the interpreter overhead, or the ~50× performance gap versus native code. The conventional escape hatches — Cython, Numba, ctypes — all force you to leave Python and write foreign code that the LLM will get subtly wrong.
Axon closes that gap without leaving the source language. AI agents that already write Python can write Axon with one extra rule: parentheses go around everything. The output compiles to the same native code you’d get from Cython, with no Python runtime in production.
Code Comparison
Section titled “Code Comparison”The same recursive Fibonacci:
Python (interpreted, no static types, no compilation step):
def fib(n: int) -> int: if n < 2: return n return fib(n - 1) + fib(n - 2)
print(fib(35))Axon (compiled to native code via QBE → clang → binary):
(fn fib ((n i64)) i64 (if (lt n (i64 2)) n (add (call fib (sub n (i64 1))) (call fib (sub n (i64 2))))))
(fn main () i32 (call print_i64 (call fib (i64 35))) (i32 0))The Axon version is more verbose — that is the price of explicit, AI-friendly syntax. In exchange you get a single binary that runs at native speed with no interpreter.
What’s familiar
Section titled “What’s familiar”| Python | Axon |
|---|---|
def foo(x): | (fn foo ((x i64)) ...) |
return x | last expression value |
if x: return y else: return z | (if x y z) |
for i in range(n): | (for ((i i64)) (range (i64 0) n (i64 1)) ...) |
import numpy as np | (import np "std/math.axs") |
print(x) | (call print_i64 x) |
def __init__(self): | structs with (fn new (...) ...) constructors |
try/except | (try ... (catch e ...)) |
| list comprehensions | (map f xs) over the collections module |
What’s different
Section titled “What’s different”- No duck typing. Every parameter and binding has a static type. The compiler rejects
(add (i64 1) "hello")at build time. - No
Nonesemantics. Use(Option T)fromstd/option_typesfor “may not exist” — the compiler enforces that you check before unwrapping. - No GIL, no interpreter. Every Axon binary is a single statically-linked native executable.
- S-expression syntax. Everything is a parenthesised list. The AST is 1:1 with the surface syntax.
- No
importmagic. Modules are explicit files; you list each one you use. - Memory management is explicit.
(alloc T)returns(ptr T),(free ptr)releases it. There is no GC. - Compiled, not interpreted. There is no
python -i myprogram.pyequivalent — you compile, then run the binary.
Idiomatic patterns
Section titled “Idiomatic patterns”| Python | Axon |
|---|---|
with open(path) as f: | (with_file path (fn (f) (call f.read))) |
@dataclass class Foo: | (struct Foo ((x i64) (y string))) |
Optional[int] | (Option i64) |
for k, v in d.items(): | (for-each d (fn (k v) ...)) |
lambda x: x + 1 | (fn ((x i64)) (add x (i64 1))) |
try / except ValueError as e: | (try ... (catch e ...)) |
When to reach for Axon vs stay in Python
Section titled “When to reach for Axon vs stay in Python”Stay in Python for:
- One-off scripts and notebooks
- Glue code that orchestrates existing tools
- Library exploration (you don’t know the API yet)
Reach for Axon for:
- The hot inner loop of a model (loss, gradient, dataloader)
- Anything that ships to production users as a binary
- Code that must run on a serverless / edge runtime with a 50MB cold-start budget
- Code where the LLM has to write the same logic 1000 times and you need it to be correct every time
Summary for Pythonistas
Section titled “Summary for Pythonistas”- Syntax: S-expressions instead of indentation. Same “batteries-included” feeling via
std/*.axs. - Performance: 30-100× faster than CPython for numeric code, no GIL, no interpreter.
- Concurrency: Green-thread cooperative scheduling via
std/evloop+ actor-style message passing. - Packaging:
axpmfor source deps,.axpkgfor binary artifacts. - Migration cost: One-time syntax learning; the underlying mental model (types, scoping, modules) maps cleanly.