Quoin
/kɔɪn/ · pronounced “coin”
A small language built from blocks — and the messages they pass.
Quoin is a Smalltalk-inspired programming language running on a virtual machine written in Rust. First-class blocks, message passing all the way down, and multi-method dispatch at the core.
- Blocks are values. Closures you can pass, store, and send messages to — the unit you build control flow from.
- Everything is a message. Even control flow is just ordinary method calls, so there's very little syntax to learn.
- Multimethod dispatch. One selector, many definitions — chosen by argument type and guards, not just the receiver.
- Gradual types. Optional annotations that sharpen dispatch, power the checker's warnings, and unlock the optimizer — nothing requires types; everything benefits from them.
- Stackful fibers. Coroutines you can yield from anywhere — generators and lazy sequences fall out for free.
- Async tasks. Spawn a fiber and the scheduler runs it concurrently, like a green thread — gather a batch or join a handle, and their I/O overlaps.
- Async I/O. Non-blocking TCP, TLS, and HTTP with a scheduler — no callbacks and no async/await coloring.
- A Rust VM underneath. Small, memory-safe, and fast.
A taste of Quoin
"* Classes with <- , methods with -> , and blocks are { } "* Types are optional — annotate where a contract matters Point <- { |@x @y| dist -> { |^Double| ((@x * @x) + (@y * @y)).sqrt } } var p = Point.new:{ x = 3; y = 4 } p.dist "* 5 "* No control-flow keywords — if: is just a message to a boolean (p.dist > 4).if:{ 'far'.print } else:{ 'near'.print } "* Blocks are values — hand one to a collection #(1 2 3 4 5).collect:{ |n| n * n } "* #(1 4 9 16 25)
Fibers — coroutines, built in
"* A Fiber is a coroutine — it yields a value, then pauses "* with all its state intact until you resume it. var fib = Fiber.new:{ var a = 0 var b = 1 { true }.whileDo:{ Fiber.yield:a; var t = a + b; a = b; b = t } } fib.resume "* 0 fib.resume "* 1 fib.resume "* 1 fib.resume "* 2 "* Wrap that same yielding block in a Generator and you get "* a lazy, infinite sequence you can take from: var fibs = Generator.from:{ var a = 0 var b = 1 { true }.whileDo:{ ^> a; var t = a + b; a = b; b = t } } fibs.take:10 "* #(0 1 1 2 3 5 8 13 21 34)
Tasks — concurrency, overlapped
"* A Task is a fiber the scheduler runs concurrently. Spawn one and it "* runs alongside you; join parks until it's done, then hands back its "* value — re-readable, like a promise. No callbacks, no async/await. use std:net/http var home = Task.spawn:{ [HTTP]Client.get:'https://example.org/' } "* ...get on with other work while it loads... home.join.status "* 200 "* Async.gather: runs many blocks as tasks at once and overlaps their "* I/O — three HTTPS fetches, TLS handshakes and all, finish in about "* the time of the slowest one. Results come back in spawn order. var sites = #( 'https://quoinlang.dev/' 'https://docs.rs/' 'https://github.com/' ) var pages = Async.gather:(sites.collect:{ |u| { [HTTP]Client.get:u } }) pages.collect:{ |r| r.status } "* #(200 200 200)v0.1.0 · public preview