Notes
2025/10/12
I've recently been reflecting on my goals for building Kombucha. On the one hand, the goal hasn't changed: I want to build a minimal and malleable programming language for symbiotic end-user programming in Rust. But if that were the only goal, success would be solely measured by Kombucha's practical use (and I'm barely using it yet), in other words by how useful its implementation is. Is that all a programming language is?
Many programming languages, Kombucha included, have a meta goal: To explore the language design space through a series of experiments. They might explore novel individual features (and Kombucha does, for example in its macro system), but most often the contribution of a language is an exploration of how different features interact.
Kombucha is exploring a specific interaction of the following areas:
Kombucha is designed as a Lisp-like language without the parentheses. To achieve this, Kombucha supports prefix call syntax, infix call syntax, as well as trailing arguments and keyword arguments. Kombucha's syntax tries to be as general as possible, so that no language constructs need to be privileged.
Out of all the experiments, Kombucha's syntax experiment is currently the most promising and complete, but it is also the most heavily dependent on other language features (most notably macros).
To be able to implement constructs such as variable assignments and pattern matching as libraries, Kombucha uses a simple macro system. In contrast to most other macro systems, Kombucha's macros are reasonable, meaning that evaluation remains fully referentially transparent without having to first expand macros.
This experiment has been the most interesting part of Kombucha's design and implementation process. While powerful enough to implement pattern matching as a library, there are still open questions and using a macro system at such an early point made debugging considerably harder. Additionally, some form of partial evaluation is necessary to optimize away the macro system overhead.
Kombucha tries to implement various control structures through effect handlers, as well as using effects in combination with a resumable bytecode VM as the standard way of interfacing with a host language.
This experiment has been largely successful, but there are still open questions when it comes to implementing the highly dynamic aspects of effects (for example, should effect handlers be chosen semi-statically based on the name of the effect or fully dynamically). Ergonomic serialization and deserialization also turned out to be more difficult than at first expected.
With lambda calculus as the starting point for Kombucha, it seemed natural to implement multi-argument functions as curried lambda abstractions. This is elegant, but increases the complexity of the VM considerably.
This experiment is very much in progress. The initial design used currying, but the next version of Kombucha might switch to fixed arity, similar to most Lisps.
One of the goals was always to design Kombucha as a highly dynamic, reloadable language that plays well with Rust, with live reload as a core feature of the bytecode VM.
This experiment is still in the design phase.