Settings

Theme

Jank – The native Clojure dialect with seamless C++ interop

jank-lang.org

174 points by giancarlostoro · 48 comments

Reader

7 threads
Jeaye

Hey folks. I'm the jank creator.

jank is a full Clojure dialect with unprecedented C++ interop. Unlike the OG Lisp/C++ combo, Clasp, there is no bridge API necessary for registering C++ functions, types, or values. jank can seamlessly interop with any C++ by just including the headers. Interop includes template instantiations, overload resolution (implicit conversions, ADL, etc), exception throwing/catching, virtual function calls, and literally everything else.

jank _is C++_, since it compiles to C++ and uses the C++ type system. It ships with a Clang-powered JIT C++ compiler to make all of the REPL goodies work. jank also improves upon the C++ build ecosystem with Cargo-like tooling.

This means you can use jank to make C++ native applications, you can embed jank into your C++ applications, or you can even use jank to just write portable Clojure libraries that people use from other Clojure dialects.

We're still in alpha right now, so things are a bit unstable. We're targeting a more stable beta release in January. The best way you can help is to try jank out and report every friction point you have on Slack, Discord, or Github.

I've been working on jank for several years. It is not vibe-coded.

goldenshale

I think repl driven development with access to native code could be a magic formula for agent engineering. No restarting, no re-compiling. Plus with persistent, immutable data structures you can iterate with many threads in parallel while maintaining sanity.

  • jwr

    It is. I'm amazed at how quickly agents can work with my Clojure code base and try things out. They make great use of the REPL.

    • bokchoi

      I dabble with clojure for some hobby projects. What's the preferred way of setting up the agent to use the repl these days? I had trouble getting the agent to use it in the past.

    • tikotus

      Can it already reliably close parens? I was disappointed some time ago, but sounds like it's ready for a new go...?

      • throw03172019

        Opus 5.5 has improved a lot on this side. I used to be so frustrated with it breaking the codebase.

        Clojure / ClojureScript codebase

      • jwr

        This was a problem with early models, I would say more than a year ago, and even then, this problem was solved completely by using the clojure-mcp tools for editing.

        Today you don't even need to use clojure-mcp for balanced editing. The models do a perfectly fine job.

        • tikotus

          Thanks! Yeah, it was probably over a year ago that I tried it. Just the thought of a statistical program coding lisp while picking the number of closing parens based on a hunch made me shiver.

      • delegate

        I'm amazed by such questions, really.

        This was true with gpt-3.5, but things have moved on, dude !

        It's like asking 'do movies have sound now?'. The answer is Yes, not just sound, but also color !

        • tikotus

          I don't know if it's quite the same. To not have seen movies with sound would have required living under a rock for decades. To not know if the paren problem has been fixed only requires not having tried it for a year, and not being part of any lisp communities.

          I'm the first one to admit my ignorance when it comes to LLM capabilities. Hence the honest question.

        • zikajk

          No, the problem still exists. It just got better.

        • waffletower

          He shouldn't be downvoted, but I haven't seen broken parens in a while.

      • embedding-shape

        The trick before was to have really short files, max 50 LOC or so, and they were OK at balancing parens. Nowadays, most SOTA models seem to be able to handle it regardless of LOC in file.

  • s_Hogg

    The first thing that comes to mind with no restarts or recompiling is the mangled variables you get in Jupiter if you're mucking around trying to get a prototype going and forget which cells have been run. I can definitely see agents having a problem with that. I would just try to make compilation fast if possible

    • kianN

      Immutability and stateless separate the nrepl from jupyter. Clojure is not strictly functional but it tends to be the most straightforward way to do most tasks in the language.

      • waffletower

        What characterizes a "functional language" often skirts history. Clojure defaults to immutable data structures and is more functional than its Lisp ancestry, although Lisp does enjoy "functional" status in all but the most religious programming circles.

        • flavio81

          A requirement for functional programming is that there's no action from a distance, thus, functions should not modify variables outside of their scope.

          This doesn't exactly mean immutable data structures are mandatory, but it helps.

          In any case, most of the functions that operate on data structures in Lisp (or Common Lisp) do it in an immutable way.

          • waffletower

            That is a projected, community-localized, requirement that ignores historic evolution of the practice. It is very interesting that machines can now be more flexible and understanding about nomenclature subtleties like this than some human engineers. Since we are adding layer after layer of pedantry -- rather than 'requirement' -- 'ethic' or 'practice' would be a more effective, practical and inclusive word choice here. The subtext of this thread, that Clojure somehow isn't a "functional enough" language to be labelled a "functional" language is narrow community prejudice.

    • chr15m

      People who are already using LLMs to drive Clojure REPLs say it works well (see #ai-driven-development on the Clojure Slack). I don't think forgetting which cells have been run is a problem with the described set up.

  • Capricorn2481

    > no restarting, no re-compiling

    Is this really a problem with agentic programming? I have done some pretty complex tasks with it and I never thought "this would go a lot faster if the compilation speeds weren't slow." Seems like the time Claude takes dwarfs any build time.

    I am not working on 1M+ LOC codebases though, so I could see how slow compilation times could be a problem then, but I imagine the agentic part would also slow down.

    • iLemming

      > Is this really a problem with agentic programming?

      State management is generally considered a difficult and complex problem. When you give a way for the agent (or a human programmer) to iterate on stuff without having to reset the state, without having to restart anything, without any (manifestly impractical) rituals, the programmer/agent stops guessing and starts empirically assessing the current state of things and reasoning about the problem space in a much tighter loop, procuring solutions that cost fewer tokens, time and effort.

      Imagine building something like a Flappy Bird game, and having to recompile whenever you tweak a moving object's trajectory calculation. What would be simpler - having the programmer mess around with values live, or having to re-compile, restart, reset the state to that point, and check where things stand?

      Programming with a Lisp REPL often feels like playing a video game. It's not just fun, it makes far better sense (in comparison)

      • Capricorn2481

        I like Lisp, I was not generally disregarding REPLs. But

        > programmer/agent stops guessing

        I think programmers and agents are fundamentally different, and require different approaches. I don't see the benefits to an agent avoiding recompilation when they may take 30+ minutes on a couple prompts. I don't think compilation time even accounts for 1% of what my agents do, but I could be wrong (again, I'm not working on something massive).

        I also don't think I want them to assume they solved something because the current image is working as intended. I don't really trust them to know if they have a working solution, or if they have built up a very specific state that works, but can't get the same solution from scratch.

        Also I feel more comfortable doing localized tests through the REPL than letting an agent do it. I would need some kind of test suite or harness to check a bigger trail of behavior than let it assume a problem was fixed. But I doubt this will be a problem for long

        • iLemming

          > I don't think compilation time

          It's not so much about time, I think you're missing the point. It's more about "staying in the flow" and in this regard, humans and agents are not much different.

          Besides, you're just ignoring the main talking point of my comment - the state. Have you ever had to restore the exact state of things in an app, when you're manipulating and changing certain behavior of it, in a specific moment and a specific combination of values? When you need to re-compile and re-load things, you inevitably end up building some elaborate scripting scaffold, just to deal with these kinds of scenarios. Live image REPLs remove that problem as a class. Immutability by default simplifies it even further.

          > I don't really trust them to know if they have a working solution

          Well, the agent can prove it by simply evaluating things live. But of course, it's never guaranteed to work the same way when started from scratch, but I'm not saying the behavior shouldn't be tested either way.

          • Capricorn2481

            > It's more about "staying in the flow" and in this regard, humans and agents are not much different.

            They are absolutely different. An LLM can be paused and pick back up in the exact same place. It makes no difference if compilation take a second or an hour. A human has to remember what they were doing. That's what people talk about when they mention flow state.

            > Besides, you're just ignoring the main talking point of my comment - the state

            I don't think I ignored that, I talk about it directly. I said it could conceivably lead to more problems because the LLM could overly lean on live evaluation as context degrades. I would feel more comfortable with it in an immutable language.

    • mike_ivanov

      Ask them what they prefer.

  • pjmlp

    Welcome to the previous AI Summer with Lisp and Prolog environments, :)

    Pity that the new Summer got to ride an interpreted language, with bindings to native libraries instead.

e12e

Wonder how this compares to clasp (common lisp c++ impl)?

flavio81

PSA: If you need a Lisp that talks to C++, Common Lisp has had seamless C++ interop in the few years thanks to the CLASP implementation. It should be fairly mature by now, I understand it was born to be used in serious projects.

  • Jeaye

    CLasp is the OG Lisp/C++ combo, but its interop is nowhere near seamless. Last I checked, Clasp requires that functions, types, and values must be registered, from C++, before being accessible in Lisp. This requires you to build a bridge between these two worlds, in C++ code. That's a huge seam.

    In jank, you just require the C++ headers, like you would in C++, and then you access whatever you want from them, like you would in C++. jank's type system is the C++ type system. jank also compiles to C++. jank includes a Clang-based JIT C++ compiler to make all of this possible.

  • spauldo

    Clojure and Common Lisp are very different beasts.

hoppp

I wish we had this a couple of years ago when I was super into clojure. Very nice stuff!

onlyrealcuzzo

This is quite cool.

``` jank is C++ jank can include any C++ source, link to any C or C++ library, and it uses the C++ type system. jank even compiles to C++! ```

I'd recommend saying that it lowers to C++ earlier, as I imagine most people are interested in that aspect of how it works.

```jank is Clojure on top of C++``` -> `on top of` could mean many things. I'd recommend just saying it transpiles to C++. Then, the pros and cons that come from that flow naturally.

``` Use your favorite nREPL editor plugin. jank contains an LLVM-based JIT runtime to compile C++ code on the fly. ```

This is true for anything written in `jank`, right? But presumably not for your C++ dependencies? Like if you have `jank` code which depends on data managed in a different C++ library.

It would seem there are a lot of concurrency and parallelism implications to this. It would be nice if you spelled that out.

``` jank builds upon Clojure Keep your existing code; unlock the native world. ```

Are there any limits here? You might want to make that clear if not. Unless explicitly stated, my assumption is that it won't always work (and therefore is mostly irrelevant). Though, in this case, it might actually always work - so that would really be worth a few extra words!

alper

Is this like Janet?

  • fp64

    It's full Clojure, immutable and stuff, with full C++ interop and native compilation. Janet is strongly Clojure influenced but more of an embedded scripting language. I like both quite a bit.

    • phillc73

      The beautiful thing about Janet is how lightweight and portable it is, no JVM.

      I use Janet for all my agentic scripting. Python is forbidden in my harness. Janet scripts for everything. Love it.

      • worthless-trash

        Please, let me know which AI you have working with janet, I find everything I try to fail horribly, i thinks its clojure.

        • phillc73

          I use Maki[1] harness and GML-5.3, GLM5.3 Flash and Deepseek-4.1 Flash 1017, with a little bit of MiMo-2.6.

          The key I've found is a strong skill. At the beginning, sure there were problems. However, I implemented an AGENTS rule that said if a Janet script failed more than twice on the same "gotcha", the correct syntax was added to the skill. The skill is regularly reviewed, consolidated and pruned. The Janet skill is a floor and loaded at the start of every session.

          Edit: Also worth mentioning is that I developed a Janet module with runtime type guards and other helpers to encode the "gotchas". https://github.com/jennystats/janet-kit

          [1] https://maki.sh

        • speed_spread

          Agents are very good at dealing with less used languages as long as you have skills defined for each. That's really the trick.

  • delegate

    jank is Clojure, but instead of the JVM it embeds Clang and LLVM, so it can understand C++ headers directly and call C++ with no bindings. Other LLVM languages (Rust, Swift, Zig, etc) are reachable the usual way, through the C ABI.

    From the TFA:

    Templates, virtual functions, exceptions, overload resolution, and RAII all just work in jank. No boilerplate necessary. Just include your headers and go! jank can include any C++ source, link to any C or C++ library, and it uses the C++ type system. jank even compiles to C++!

  • mike_ivanov

    More like Jolt

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection