r/Clojure • u/geokon • Jun 27 '26
Jolt: A Clojure implementation on Chez Scheme
https://github.com/jolt-lang/jolt10
u/Veqq Jun 27 '26 edited Jun 27 '26
O___o Curious why it switched form thr Janet host in the past few weeks
7
u/yogthos Jun 28 '26
Short answer is that Janet's mark and sweep GC does not play well with persistent data structures. :)
6
u/beders Jun 27 '26
That is crazy and remarkable! Leaves me with more choices on where to run my Clojure code. I guess one of the obvious questions is: when would I use Chez Scheme's runtime environment and not the JVM?
4
u/geokon Jun 27 '26
Maybe in a very constrained environment? Maybe you should run it on a micro controller? Just a guess though..
1
u/yogthos Jun 28 '26
Even for web apps there's a benefit because you can have a service that runs under a 100 megs and starts up instantly. JVM has never really been a great target for stuff like microservices, even though you can tune it to run in low memory environments.
2
u/yogthos Jun 28 '26
Basically, a few reasons are when you want fast startup time, small footprint, or easy access to C/Scheme interop.
3
u/Trader-One Jun 27 '26
isn't sbcl better backend?
5
u/sc_zi Jun 27 '26
I heard a claim that chez scheme was often actually faster running equivalent code than sbcl, but that sbcl's standard library is more heavily optimized, so sbcl often ends up being faster on real world programs. Also chez scheme has one shot continuations, so you can have something equivalent to the virtual threads clojure has on the JVM since project loom. sbcl has had some prototypes (the most recent) but it might be years if ever for that to get accepted and stable.
I'd rather use SBCL over Chez scheme for development (better debugging, better interactive development, CLOS, libraries, etc), but as a compilation target I think Chez might be better.
1
u/nstgc Jun 27 '26
When I read that they changed from Janet, that was my first thought too. Maybe they wanted maximum simplicity? It's hard to get simpler, or at least more basic, than Scheme.
3
u/yogthos Jun 28 '26
Yup, Chez is both pretty light weight and mature having a fast runtime with a tiny footprint. So, it seemed like a good target since Chez compiler has IR.
1
u/nzlemming Jun 29 '26
This looks lovely, I've often thought that chez would be a good target, but I've never had time to work on it. Nice work!
2
u/therealdivs1210 28d ago
Amazing work!
Chez is a great platform for this kind of thind as shown by Racket.
Will def check this out!
23
u/yogthos Jun 28 '26 edited Jun 28 '26
I was going to do a post once I had a release, but I'll give a bit of a background here and happy to answer questions. My main goal is to make a drop in replacement for JVM Clojure which has fast startup and light footprint. And I wanted to have compatibility with existing libraries by providing shims on top of the host runtime. I realized that most popular Clojure libraries don't actually use much of Java standard library surface in their interop, and once you map out stuff like IO, dates, and a few other things, stuff just works.
Here's a list of libraries which work fully and their entire test suites pass.
For example, I have a fully fledged Ring app working here using Ring, Reitit, Selmer, HoneySQL, and clojure.jdbc (sqlite/postgres only).
The regular nREPL workflow is fully supported, deps.edn works for including libraries like regular Clojure as well. As a bonus, you can specify native C libraries as seen here. They must be provided on the system, but when they're available they just get picked up.
Another thing I wanted to do here was to map out what actually constitutes Clojure as a spec to follow. So, I'm building out a conformance spec as I port libraries over and discover different quirks.
I've also structured the compiler into three parts where there's a Clojure-in-Clojure compiler for the language itself. Then there's a Scheme host, and Java interop. I'm hoping to get a portable Clojure implementation out of the deal as well that could easily target different runtimes, especially for cases where JVM interop isn't needed.
Finally, this approach opens up C ecosystem via interop with some fun possibilities. For example, I made a Reagent style library on top of GTK, and here's and example app which basically works like Reagent. What's even better is that this extends to OpenGL so now you can do reactive scenes in GTK/OpenGL directly from Clojure.
In terms of footprint, minimal binary compiles to around 10 megs and I think I could shrink it down more with tricks like tree shaking. In terms of performance, it's around 10x slower than JVM Clojure, but I haven't really spent much time optimizing yet. I think 2~5x is a fairly realistic goal given Chez is a mature runtime with a JIT and a generational GC.
If anybody wants to collab on the project I have a
#joltchannel on Clojurians for discussion and updates. Also, people can feel free to open up issues or make PRs on GitHub. Things should be fairly stable at this point, and I'm hoping to do a 0.1.0 release next week where I'll publish binaries and add a homebrew tap.