2 min · 386 words programminggolangclojurelispsoftware-design

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