Glojure is a Clojure interpreter built in Go that treats Go values as Clojure values and vice versa, unlike other Go ports that compile to bytecode or run as separate processes.
A new Clojure implementation called Glojure takes a different approach to running Clojure on Go. Instead of compiling to bytecode or operating as a separate process, it embeds itself directly into Go's runtime.
Glojure is an interpreter for Clojure hosted on Go. The project provides access to Go libraries in the same way Clojure accesses Java frameworks. Go values work as Clojure values throughout the system.
The project remains in early development. The team warns of bugs, missing features, and limited performance. Backwards compatibility is not guaranteed before a v1 release.
That hasn't stopped people from using it. Hobby projects run a meaningful subset of the transformed core Clojure library.
What "hosted" means in practice
Glojure calls itself a "hosted" language. This term describes languages built in terms of a host language. For Clojure on the JVM, all Java values are also Clojure values. Glojure aims for the same relationship with Go.
Other Go implementations of Clojure take different approaches. Joker runs as a bytecode interpreter. let-go uses a tree-walk interpreter and adds a GIL for concurrency. Glojure also uses a tree-walk interpreter but avoids the GIL and adds extensible interop.
The key difference: Glojure's interop layer lets you expose any Go package to Clojure code at compile time. You generate a package map file that exports Go functions to the Clojure runtime.
Two ways to use it
Glojure works as either a standalone tool or an embedded library.
The standalone glj command provides a traditional Clojure development experience. You get a REPL with vi and emacs editing modes, multiline input, tab completion, and persistent history across sessions.
You can evaluate expressions from the command line or run Clojure scripts directly. The glj -e flag evaluates code in one shot.
For embedding, you import the Glojure runtime into your Go application. The runtime.ReadEval function executes Clojure code and returns Go values. You can expose Go functions to Clojure and call Clojure functions from Go.
This makes sense when you want users to extend your application with Clojure plugins, or when you need to mix Go's performance with Clojure's expressiveness in a single binary.
Interop by default
Glojure ships with built-in interop for many Go standard library packages. These include net/http, os, fmt, sync, reflect, strings, and time.
Package names get munged to avoid ambiguity. A forward slash in a Go package name becomes a colon in Glojure. This keeps namespace symbols unambiguous.
You can extend the interop layer beyond the standard library. The gen-import-interop tool generates Go files that export additional package functions to the Glojure package map.
Numbers work differently
Clojure on the JVM maps types to JVM types. Glojure maps them to Go types. The differences are subtle but real.
Clojure's long becomes int64 in Glojure. double becomes float64. Go bytes are unsigned while JVM bytes are signed. JVM integers are 32-bit regardless of platform, while Go integers are 32- or 64-bit depending on the system.
Glojure also wraps Go's big.Int, big.Float, and big.Rat types for BigInt, BigDecimal, and Ratio operations.
The numbers don't lie
Glojure is early software. The team asks users to install Go 1.24 or higher and build from source.
The project targets developers who want Clojure's syntax and macros running directly in Go programs. It sidesteps the JVM entirely.
The GitHub repository includes documentation on both standalone and embedded usage. The cmd/glj package provides the standalone tool. The pkg/runtime package handles embedded evaluation.
For developers building platforms that users extend with Clojure, Glojure offers a path to mix two language runtimes in a single process. That's not something most Go ports of Clojure can claim.

Comments
Please log in or register to join the discussion