Beamtalk Design Principles

Status: Complete — Core design philosophy. Updated 2026-03-20 to reflect ADR 0004 (persistent workspaces), ADR 0036 (metaclass tower), ADR 0059 (supervision trees), MCP server, and multi-interface architecture.

Core philosophy guiding beamtalk design. These inform all implementation decisions.

For detailed syntax and features, see Language Features. For syntax design rationale, see Syntax Rationale.


1. Interactive-First

Beamtalk is a live environment, not a batch compiler.

Implication: Workspace tooling is first-class, not an afterthought. The same live workspace serves REPL, VS Code, and AI agents (via MCP) over one WebSocket protocol.


2. Hot Reload is Core

Code changes apply to the running system without restart.

Implication: Generated code must support BEAM's code upgrade patterns.


3. Actors for Concurrency, Values for Data

Object is the root — two specializations map to natural BEAM concepts (ADR 0067):

Implication: The data keyword (field: vs state:) signals which BEAM concept the class maps to. Actor instantiation creates processes; value types compile to direct operations; plain Object subclasses are method containers.


4. No Image, But Live

State persists in running processes, not a monolithic snapshot file.

Implication: The workspace is the live system. Reconnecting picks up where you left off — actors, state, loaded modules all persist.


5. Code Lives in Files

Source code lives in the filesystem, not in a binary image.

Why this matters:

Implication: Compiler reads from filesystem; tooling writes changes back to files.


6. Messages All The Way Down

Everything is a message send, following Smalltalk/Newspeak philosophy (with pragmatic BEAM-specific adaptations—see Syntax Rationale).

Implication: Even basic operations compile to message sends (optimized where possible).


7. Sync-by-Default Actors with Explicit Cast

Inter-actor . message sends are synchronous (gen_server:call) — they block the caller until the actor replies. Fire-and-forget sends use the explicit ! operator (gen_server:cast).

Implication: Actor communication is synchronous by default, giving a natural call-and-return model while preserving full BEAM process isolation. Use ! when you explicitly want non-blocking dispatch.


8. Reflection as Primitive

Full runtime introspection is a language feature, not a library.

Implication: Compiler preserves metadata for full introspection. The system is self-describing — code is queryable, not just readable.


9. Seamless BEAM Ecosystem Integration

Beamtalk is a first-class BEAM citizen, not an isolated language.

Interop is not an afterthought — it's essential for adoption. The BEAM ecosystem has decades of battle-tested libraries (OTP, Phoenix, Ecto, Nx). Beamtalk must use them seamlessly.

Design principles:

Why this matters:

Implication: Generated code follows BEAM conventions exactly. Foreign function interface is simple and low-friction. Build tools integrate with Mix/Rebar3.


10. Fault Tolerance via OTP

Embrace BEAM's "let it crash" philosophy — actors crash independently, the supervisor restarts them.

Implication: Fault isolation is guaranteed. Supervision is native Beamtalk syntax — no Erlang FFI needed.


11. Live Patching is a Message Send

Hot code reload is just message sends to class objects — no special syntax.

Implication: No dedicated syntax needed — live patching falls out naturally from "everything is a message send."


12. Compiler is the Language Service (TypeScript Approach)

The compiler is architecturally designed for tooling, not adapted for it later.

Following Anders Hejlsberg's TypeScript principle: the compiler IS the language service. They are the same code path, not "compiler + separate LSP wrapper."

Architecture requirements:

The compiler answers questions:

Implication: Compiler architecture is designed for responsiveness first, batch compilation second. Code generation is just one of many services the compiler provides.


Non-Goals (For Now)


References