23 comments

[ 4.8 ms ] story [ 55.0 ms ] thread
Aside from the lack of JVM, what's holding back Jank from being a drop in Clojure replacement?
Hey folks. I'm the creator of jank. I didn't expect to be on HN today, but I appreciate the interest.

In short, jank is Clojure, but it's on LLVM and has seamless C++ interop. You still get full nREPL capabilities, can redefine anything on the fly, and we can actually JIT compile C++ code alongside your Clojure. The seamless C++ interop is first of its kind, for a lisp, and is done by JIT compiling C++ alongside the LLVM IR we generate for jank and then stitching them together into one IR module.

Note, jank isn't released yet. I'm targeting the end of this year for the first alpha release. I put out monthly development updates on the jank blog, with the next one coming out this week.

I'm very excited about jank, and it's on my backlog.
I love this project. I've been a sponsor on GitHub since late last year.

But for the love of... please pick a different name.

Whatever reasons companies/teams will have for not letting someone use Jank at work, don't let the name be one of them.

Since this appears to be the marquee feature (compared to the well regarded Clojure) it would be good to see some benchmarks comparing the JVM to LLVM versions.

This allows jank to offer the same benefits of REPL-based development while being able to seamlessly reach into the native world and compete seriously with JVM's performance.

I'm especially excited about the error reporting in jank. Fingers crossed they will live up to the blog post showcasing them. Most people I convince to give Clojure a shot tell me that they are utterly confused about its error messages.
I remember Clapp a Common Lisp in C++ using LLVM. Clapp was promising but progress has been very slow. Since Clojure is similar to CL, one wonder if Jank will experiment similar problems. Might I ask the author of Jank whether he knows about Clapp and if so, how will this project try to avoid getting stagnated?

Edited: Here is a post in HN from 2014 about Clapp. https://news.ycombinator.com/item?id=8367404

In that post and comments we read that Clapp was 100x slower that sbcl, and the author of Clapp claimed: "LLVM is a great library for implementing C and C++ but more work needs to be done to support Lisp features like closures and first-class functions. We are working on that now".

I hope Clapp's author work in the last 11 years could help today efforts. Surely, the LLVM of today is not that of 11 years ago. Anyway, IMHO, sharing some knowledge could be productive for any project that is about C++, Lisp or Clojure using LLVM.

If I recall correctly, compiling Clapp takes a full day, that gives not a good vibe.

On the happy path, I think that Julia transpile to LLVM, but Julia is the result of many men working years at it. Honestly, I don't think that one single programmer to be able to create such a big project as a performant clojure in C++ will the ability to compile code quickly. Getting sbcl speed and compilation speed would be an extraordinary feat!

In Go there were great sacrifices to get fast compilation, and the problems to include generics, trying to avoid blows up compilation because some type checking is NP-complete.

Also perhaps ECL, a lisp in C, can gives us some hints about how to get better performance and compilation speed.

Perhaps I am just too old to be open to new dreams, anyway I hope the best to this project and I thank to Clojurists Together for supporting this project. It must be very intellectual rewarding to work in a project whose aim is to extend and improve your favorite computer language. But the journey will be no an easy one, that's for sure.

How does programming with Clojure targeting multiple platforms (JVM, JS, CLR, LLVM, ...) work?

Are there Clojure libraries that don't use JVM(/JS/...)-specific stuff that works on any Clojure platform/dialect? Can such libraries be used on Jank out of the box? Or do library authors have to do something explicit in their libraries to enable their use in specific platforms/dialects?

Great work! Also, the error messages are neat!
I am once again calling for someone to make something that's "basically clojure" but with whitespace instead of parens.

Parens don't matter, but giving values names causing indentation is something I simply cannot abide as a terminal intermediary value name giving person.

EDIT: oh and also something with "proper" multiline comments. Thanks!

I feel like I’ve been coding jank already for most of my life.
Good luck, jeaye.
Was a little surprised to discover this was a real language and not an esoteric or joke language.
I love Clojure, I really do, but it feels to me like what I once thought was its unstoppable march ground to a halt and then it kinda fell out of the nerd consciousness. I’m hopeful jank might be the shot in at arm Clojure needs to get going again.
What is jank's tooling like? Clojure's felt very much like an afterthought, unfortunately. I do like having a decent set of tools right out of the box. I think Gleam was smart in this respect.
jank will lean heavily into leiningen, though it will have deps.edn support. I think that the process of doing this is much simpler than whatever Clojure CLI devs are doing these days:

    lein new jank hello-world
    cd hello-world
    lein run
    lein test
    lein package
Going forward, we'll see about a leaner version of lein. Maybe we can fork lein and compile it in jank or maybe we'll need to make our own. For now, default lein will be the recommendation.
Hey, as someone who spent a few years reimplementing another language trying to decouple it from JVM (Scala JVM -> Scala Native), some pitfalls to avoid:

- Don't try to provide backwards compatible subset of JVM APIs. While this might seem tempting to support very important library X with just a bit of work, I'd rather see new APIs that are only possible with your language / runtime. Otherwise you might end up stuck in never-ending stream of requests to add one more JVM feature to get yet another library from the original JVM language running. Focus on providing your own unique APIs or bindings to native projects that might not be easy to do elsewhere.

- Don't implement your own GC, just use mmtk [1]. It takes a really long time to implement something competitive, and mmtk already has an extensible and pluggable GC design that gets some of the best performance available today [2] without much effort on your end.

- Don't underestimate complexity and importance of multi-threading and concurrency. Try to think of supporting some form of it early or you might get stuck single threaded world forever (see CPython). Maybe you don't do shared memory multi threading and then it could be quite easy to implement (as in erlang). No shared memory also means no shared heap, which makes GCs's life much easier.

- Don't spend too much time benchmarking and optimizing single threaded performance against JVM as performance baseline. If you don't have a compelling use case (usually due to unique libraries), the performance might not matter enough for users to migrate to your language. When you do optimize, I'd rather see fast startup, interactive environment (think V8), over slow startup but eventually efficient after super long warmup (like jvm).

I see that jank is already doing at least some of the things right based on the docs, so this message might be more of a dump of mistakes I've done previously in this space.

[1]: https://github.com/mmtk/mmtk-core

[2]: https://dl.acm.org/doi/pdf/10.1145/3519939.3523440

> Don't try to provide backwards compatible subset of JVM APIs.

Yeah, jank doesn't much with JVM APIs or the JVM at all. We have our own implementation of the compiler and runtime. It has similarities to Clojure's design, only because the object model somewhat demands that.

> Don't implement your own GC, just use mmtk [1].

Yep, already the plan. Currently using Boehm, but MMTK is the next upgrade.

> Don't underestimate complexity and importance of multi-threading and concurrency.

Clojure aids this in having STM, immutable data structures, etc. However, there are some key synchronization points and I do need to audit all of them. jank doesn't have multi-threading support yet, but we will _not_ go the way of Python. jank is Clojure and Clojurists expect sane multi-threading.

> Don't spend too much time benchmarking and optimizing single threaded performance against JVM as performance baseline.

This year, not much optimization has been done at all. I did some necessary benchmarking early on, to aid in some design decisions, but I follow this mantra:

1. Make it work

2. Make it correct

3. Make it fast

I'm currently on step 2 for most of jank. Thanks for sharing the advice!

how does memory management work? malloc and such?
Having scanned the source, I believe there is a better design for this language.

There exists a much smaller subset of jank that is capable of compiling itself. I am quite sure that you could write a bootstrap compiler in clojure (but restricted to the same subset) that translates to clojure (or some other language you prefer targeting). My guess, from experience writing small compilers, is it should be doable in ~5000 lines or even less.

Once you had that, you could then write a backend that translates to c. This gives you a native compiler for this small subset of jank. Applied to its own source code, you get a native compiler binary for free and cut the cord from clojure.

Now you have a native compiler and a very small, tight language. Because it is so small, it is easy both to check correctness and optimize. You can add new backends relatively easily. For the repl, you can compile functions into their own hash-addressed shared libraries using a c compiler and dlopen them. TCC is very fast for this purpose even if the generated code isn't quite as good as optimized gcc or clang.

All of the future vision could be implemented on top of this foundation. The current approach is likely going to just bog the author down, dealing with accidental complexity from c++ and llvm especially. It is also better to have fewer features implemented completely and correctly than more features incompletely or incorrectly implemented.

I was a Clojure fan back around 2011. I'm just curious how you make a living with these esoteric languages? I was able to build exactly two back-end services using Clojure as a PoC back then, which was 14 years ago, and then the whole Clojure thing basically died. I'm shocked to see any resurgence of it or LISP in 2025.
had a bunch of projects (long lived infra projects) until a few years ago and nowadays i mainly use it for scripting (with babashka). changed job to a startup a few weeks ago, so some more clojure getting in there!

plenty of jobs don't mandate languages on everything.