The shape of Clojure, the runtime of Go
Discover how the unlikely marriage of Clojure's expressive form with Go's efficient runtime gives birth to a groundbreaking new language.
I have two favourite languages. They disagree about almost everything.
Go wants types, a compiler, a single binary, and no surprises. Clojure wants parentheses, immutable data, and the freedom to bend the language toward the problem instead of the other way around.
I stopped trying to pick one. I built a language where they share a parser.
It's called golisp. Clojure-style S-expressions in, Go out. Not an interpreter pretending to be fast — a transpiler. You write Lisp, it emits Go, the Go compiler does the rest.
(defn ^string greet [^string name]
(str "Hello, " name "!"))
(defn main []
(fmt/println (greet "World")))
The caret carries the types. ^int, ^string, ^[string error] for the multi-return that defines so much idiomatic Go. The annotations aren't decoration; they become the Go signatures.
What I wanted was the shape of Clojure with the runtime of Go.
So map, filter, reduce, range, take, drop. Sets as #{1 2 3}. The map operations — assoc, dissoc, merge, keys, vals. The vocabulary I reach for without thinking.
And underneath it, Go's machinery, exposed rather than hidden:
(go (fmt/println "async"))
(defer (fmt/println "cleanup"))
(let [ch (chan ^int 1)] (send! ch 42) (recv! ch))
Goroutines, defer, channels. The good parts of Go aren't abstracted away — they're given parentheses and handed back.
Because it compiles to Go, it inherits Go's best trick: the static binary.
glisp build produces something with no external dependencies, which means it runs in a scratch image. No base OS. No shell. Just the binary. Eight to fifteen megabytes of program and nothing else.
A Lisp that ships as a container with zero attack surface is a sentence I did not expect to write.
There's a small web layer too — handlers are Request → Response, both aliases for map[string]any — and enough editor support to make it real: a Neovim plugin, and an LSP with diagnostics, hover, and jump-to-definition. A language you can't navigate isn't a language. It's a museum piece.
I'm not claiming the world needs another Lisp. It doesn't.
But the two ideas I keep returning to — the expressiveness of the form, the discipline of the output — turned out not to be in conflict. They just needed a place to meet.
The code is here: github.com/leinonen/golisp-language