Hello, Makoto
Goal: understand why Makoto exists, install the toolchain, and run your first program.
The pitch
Section titled “The pitch”Makoto combines four bets that normally come separately:
- BEAM resilience (Erlang): isolated processes, structural supervision, let it crash. A process that fails does not corrupt the rest.
- Go concurrency:
spawncreates cheap processes; they talk to each other over typed channels. - Rust types, without lifetimes: sum types, generics, exhaustive pattern matching, without the borrow
checker and without
'ainfecting signatures. - Zig comptime: metaprogramming in the language itself, arbitrary-width integers, first-class FFI-C, IO without coloring.
And three “nos” that define the language’s character:
- No
null: absence isOptional[T], explicit in the type. - No
unit/void: a function that does not return a value simply has no-> T. - No function coloring: there is no
async; the scheduler suspends the process on IO, and no function needs to be marked.
The philosophy, in one sentence: consistent, not simple. You only pay for what you summon.
Install and run
Section titled “Install and run”The toolchain is a single binary, makoto, with the alias mk. Core source files end
in .mko.
use io
fn main() { io.println("Hello, Makoto!")}mk run ola.mko // compile and runmk build ola.mko // just compile → binaryNotice a few things that already show up in hello world:
use io: there are no functions in global scope. Evenprintlnis imported (printlives inio,panicinruntime). Whoever does no IO never seesio.mainhas no-> T: it does not return a value. With novoid, the absence of->is the absence of a return."{{ }}"will show up in the very next program: string interpolation.
use io
fn main() { nome := "world" io.println("Hello, {{nome}}!") // interpolation via {{ }}, through the Display interface}nome := "world" declares an immutable value (the common case carries no ceremony). In the next
chapter we break down declaration, the primitive types, and why there is no null.
Next: 01 · Values and types