r/Clojure • • 1d ago

Lambda performance comparison of running different Clojure dialects

Thumbnail
github.com
20 Upvotes

r/Clojure • • 2d ago

Jonquil: a pragmatic editor for the Lisps you use

Thumbnail
jonquil.b12n.app
21 Upvotes

r/Clojure • • 2d ago

I built myself a Jolt app to retouch my photos, it supports RAW files and the operations I commonly use for retouching such as noise removal, sharpening, and color correction

Thumbnail
github.com
18 Upvotes

r/Clojure • • 3d ago

Porting Ideas, Not Code - Delaney Gillilan (Clojure/Conj 2026)

Thumbnail
youtube.com
28 Upvotes

Clojure changed how many developers think about data: immutable facts, temporal structure over time, and code as data. But what changes when these ideas move beyond the Clojure ecosystem? Stardust explores how Clojure and Datomic concepts can be reimagined in a language-agnostic data platform for messy, real-world open data. It looks at what transfers cleanly, what requires new trade offs outside the JVM, and how real-world measurement reshapes system design. It’s not about preserving a stack, but about carrying forward ideas like simplicity, compatibility, and care for data across different languages and systems.

Speaker: Delaney Gillilan, Synadia, Senior Product Strategy Engineer

Delaney has a rich and varied background from full stack game development, military systems of record, gambling and slot machines, to even a stint in the circus. He has a love for creating tools and engines for other creators to use and moves fast!


r/Clojure • • 3d ago

Mutable Locals in Clojure, the Hard Way

Thumbnail tailrecursion.com
25 Upvotes

r/Clojure • • 3d ago

Clojure Agent Framework

Thumbnail
github.com
10 Upvotes

clj-agent is a modular Clojure AI Agent framework built around a ChatClient central orchestrator. It provides a deftool macro for tool definitions, multi-level invoke APIs, and onion-style Filter middleware mirroring Spring AI 2.0 Advisors — including ToolSearch progressive tool disclosure, RAG injection, and self-correcting structured output, all with zero added dependencies. Its dependency-inverted architecture separates a zero-dependency core, an agent runtime (ReAct loop, ChatMemory, HITL approval), and provider adapters for Anthropic, OpenAI, Gemini, Ollama, and other OpenAI-compatible services. All nine modules publish to the Clojars im.ttalk group, so you depend only on what you need.

The README: https://github.com/TTalkPro/clj-agent/blob/main/README_EN.md

The clojars: https://clojars.org/groups/im.ttalk

And I use this code in my own production, https://ttalk.im/products/jinshu/ https://ttalk.im/products/guanlan/


r/Clojure • • 3d ago

Instead of using `comp` and often wasting computation, here's how to reverse `->` and `->>` when you want `comp`'s ordering without its cost, etc.

15 Upvotes

Hello everyone. This is my first Clojure subreddit post by the way, if my memory is correct. I am actually debating using Clojure (+Java) vs Zig for my next project, but I've been learning Clojure and reflecting upon the fact that in programming languages (and in natural language prose text too for that matter) the order in which words appear in an expression has a substantial effect on readability and on what parts feel like they are being emphasized and brought to one's attention.

Consider, for example, the difference in emphasis and ease of code navigation between the following two equally valid Clojure expressions:

(assert (not (zero? 1)))
(-> 1 zero? not assert)

The former is the most "naive"/direct way of writing it, whereas the later has the strongest left to right flow of action. However, notice that though the latter expression is more elegant, it makes the visibility of the assertion worse by putting the assert keyword at the end. Some people may also find "zero not" to sound too "Yoda-like" (akin to concatenative programming languages like Forth and Factor) whereas something like "not zero" may sound more natural to some people.

I also thought about how comp (compose functions) could be used here to keep the "not zero" ordering, but then a function call cost may be imposed by doing so if the optimizer doesn't remove it.

So, that got me thinking that I should try writing a reversed version of the -> and ->> macros and I did and here are the resulting definitions:

(defmacro <- [& rest] 
  (let [rev-rest (reverse rest)] 
    `(-> ~@rev-rest)))

(defmacro <<- [& rest] 
  (let [rev-rest (reverse rest)] 
    `(->> ~@rev-rest)))

Both were actually very easy to write, as you can see.

This allows you to write the following:

(<- assert not zero? 1)

As you can see, this enables you to reorder things according to what feels most natural in any given context, which helps draw the attention of anyone reading your code to what comes first in each expression, much like how in English the first thing we start a sentence with is what is being emphasized or is assumed to be the subject (as in active vs passive voice, etc).

This especially is well suited to assertions because what is most important about an assertion for someone trying to scanning code quickly is that it is an assertion and hence emphasizing that clarifies it.

This is in contrast to data flow or transformation pipelines that use -> and such, where the opposite order often feels better.

One can also see by applying macroexpand and/or macroexpand-1 that the cost of these macros in run-time will be zero, relative to simple/"naive" nesting, given that the expressions (macroexpand '(<- assert not zero? 1)) and (macroexpand '(assert (not (zero? 1)))) return identical expansions.

Cognitive load tends to increase non-linearly with how many nesting levels something has, so using "threading"/pipeline macros flexibly and often tends to help readability and these new variants help fill those potential use cases out better.

So, clearly both orderings should be in your toolbox for legibility and I would argue that this should even be made part of the standard library perhaps since it is such a common case.

I am personally am really happy with the resulting freedom.

With these new macros in hand one is much less likely to use the less legible nested forms when you can now order things either way.

(PS: Thanks for reading and for your time! 😎)


r/Clojure • • 4d ago

Transforming Software Evolution by Adam Tornhill at Func Prog Conf

Thumbnail
youtube.com
21 Upvotes

Lisp has promised simplicity and expressive power for six decades, yet never reached the mainstream. Ten years ago, CodeScene made a big bet on a modern Lisp dialect, Clojure, to build a platform for tackling technical debt.

This talk explores how Clojure’s metaprogramming, embedded domain-specific languages, parallelism, and multi-methods helped a small Swedish company compete with teams 20 times its size.

Drawing on a decade of building CodeScene, Adam reveals how language choices can shape productivity, innovation, and engineering culture—and how innovations in agentic coding fit into the picture.


r/Clojure • • 4d ago

London Clojurians Talk: Programming a business to improve itself (by Christian Weilbach)

Post image
16 Upvotes

THIS IS AN ONLINE EVENT
[Connection details will be shared 1h before the start time]

The London Clojurians are happy to present:

Christian Weilbach (https://christian.weilbach.name) will be presenting:
"Programming a business to improve itself"

Christian shows Simmis, a workspace where people and AI agents share one versioned memory of chat rooms, a wiki, a double-entry book and the code that runs them, and where every attempt happens on a fork. Participants will see agents benchmark and improve workflows in forked rooms and bring their results to review as proposals, turning the REPL loop of fork, attempt, measure and adopt into a way to program a business. He argues that programming such organisations, more than a single smarter model, is what programming AGI will look like in practice.

Christian Weilbach is the CEO of Simmis, which builds software for organisations of people and AI agents. He leads the development of Datahike, a git-like Datalog database, and the replikativ family of Clojure libraries for forkable state, synchronisation, probabilistic inference and accounting. He holds a PhD in machine learning from the University of British Columbia and has spoken at Clojure meetups since 2017, most recently on rethinking programming as inference for the Simmis project at London Clojurians in May 2026.

If you missed this event, you can watch the recording on our YouTube channel:
https://www.youtube.com/@LondonClojurians
(The recording will be uploaded a couple of days after the event.)

Please, consider supporting the London Clojurians with a small donation:

https://opencollective.com/london-clojurians/

Your contributions will enable the sustainability of the London Clojurians community and support our varied set of online and in-person events:

  • ClojureBridge London: supports under-represented groups discover Clojure

  • re:Clojure: our annual community conference

  • monthly meetup events with speakers from all over the world

  • subscription and admin costs such as domain name & StreamYard subscription

Thank you to our sponsors:

RSVP: https://www.meetup.com/london-clojurians/events/317380055/


r/Clojure • • 4d ago

clj-pulse: a fast Clojure language server

Thumbnail
bogoyavlensky.com
20 Upvotes

r/Clojure • • 4d ago

Rendering in batches with glimmer and Datastar

Thumbnail yogthos.net
10 Upvotes

r/Clojure • • 5d ago

The Code Was the Easy Part - Arthur Fücher (Clojure/Conj 2026)

Thumbnail
youtube.com
22 Upvotes

r/Clojure • • 5d ago

DatomicConf 2026 speaker lineup

20 Upvotes

The Datomic developer success team is excited to announce the speaker lineup for DatomicConf 2026!

This year, we’ll hear from an outstanding group of speakers: Paul Rutledge & Dave Gonsalves, Chris Cyrus Hapgood, Fabian Merkle, Luana Amorim, Benjamin Kamphaus and Francis Avila, plus Datomic Core Dev news straight from Ghadi Shayban. We’re also putting together an evening of lightning talks featuring even more speakers.

Join us on December 11 in Durham, North Carolina. Registration is open and free! You can also sign up for the livestream. See the full talk descriptions and event details at https://conf.datomic.com/


r/Clojure • • 5d ago

Two apps one process

Thumbnail andersmurphy.com
27 Upvotes

r/Clojure • • 6d ago

State of Clojure Community 2026

Thumbnail
surveymonkey.com
41 Upvotes

If you use Clojure or one of its ever growing family of dialects, please contribute to the annual State of Clojure survey! We've been running this since 2010 and it is a vital source of information about how people are using Clojure and the many tools and libraries around it. Thanks!


r/Clojure • • 6d ago

Smuggling Clojure into Statically Compiled Video Games with Silk - James Tolton (Clojure/Conj 2026)

Thumbnail
youtube.com
36 Upvotes

r/Clojure • • 6d ago

Jolt bindings for UPBGE to control the engine via nREPL

Thumbnail
github.com
15 Upvotes

r/Clojure • • 6d ago

Markdown to HTML in Clojure today: markdown-clj, nextjournal/markdown, or a Java library?

14 Upvotes

There are several ways to turn markdown into HTML from Clojure now: markdown-clj, nextjournal/markdown (built on CommonMark), or a Java library such as flexmark or commonmark-java through interop.

  • Which do you use, and does it handle tables and the other GitHub extras properly?

  • Do you need it to run in ClojureScript as well?

  • Does anyone parse markdown into data (hiccup) and work on that, rather than going straight to HTML?

I use markdown-clj (in mdserve-starter, a local markdown viewer), and it needs a few workarounds for cases it renders wrongly, which is why I'm asking.


r/Clojure • • 9d ago

Compiling Clojure in Parallel using Bazel - Allen Rohner (Clojure/Conj 2026)

Thumbnail
youtube.com
16 Upvotes

r/Clojure • • 9d ago

Starting a new project today: clojure.spec or Malli?

33 Upvotes

clojure.spec is still spec.alpha, and spec-alpha2 has no releases yet. Meanwhile Malli has become very popular.

So, for a new project today:

  • clojure.spec, Malli, or something else, such as Plumatic Schema?

  • If you stay with spec, what keeps you there?

  • If you moved to Malli, what made you switch?

  • Or do you not spec at all? The projects I work on use neither, and I've found no cause to complain.


r/Clojure • • 9d ago

Wagoe 1.1.1 — authorization, and the access-control bug the authorization release shipped with

14 Upvotes

Wagoe is a batteries-included Clojure framework I've been building for a couple of years; 1.0 landed end of September. 1.1 is the authorization release.

What's in it. Permissions, roles and scopes: modules declare them, groups hold them, routes check them. New apps enforce from the first run; existing apps stay :off until you flip it, and bb upgrade authorization check tells you who would lose access before you do.

The part I actually care about is that it answers questions instead of just enforcing. Pick a user and a permission and the admin tells you yes or no and which group made it so. Change a group or a role and you see who gains and who loses what before anything is written. Memberships can expire on a date. There's a rights timeline per user, so "who gave them that?" doesn't end in a log search.

The part I'd rather say myself. 1.1.0 shipped an access-control bug in the admin. List pages let you filter and sort on fields the entity hides, so someone allowed to read users could recover password hashes and MFA secrets a character at a time. Fixed in 1.1.1, advisory GHSA-g896-jm3g-34h6. Install 1.1.1, not 1.1.0. CI now opens every page of a freshly generated app on SQLite, PostgreSQL and MySQL, so that class of bug fails the build instead of reaching you.

Yes, the authorization release shipped with an authorization hole. I'd rather you hear it from me.

State of it. 28 libraries across the foundation, application and extension tiers, plus 5 developer-tooling libraries: 33 artifacts under com.wagoe, all on 1.1.1. Eight of the 28 are marked incubating and sit outside the SemVer promise —config, ai, geo, external, reports, audience, webhooks, workflow — with the reason per library on the stability page. Solo project, bus factor one.

Happy to answer anything about the authorization model, or about why a framework at all in Clojure.


r/Clojure • • 9d ago

golem: a mock REST server generated from your Malli schemas or clojure.spec specs

14 Upvotes

A frontend needs large amounts of hand-written fixture JSON before a backend exists, so I wrote golem: point it at your Malli schemas (or clojure.spec specs) and it serves a stateful REST API with generated data.

N.B. Yes, I used Claude Sonnet 5.5 to write this. No, I'm not ashamed. It works and the entire project was cranked out in less than three hours of wall-clock time. Anyone who doesn't use this kind of force multiplier for tooling is foolish.

Repo: https://github.com/frankadrian314159/golem (MIT)

The simplest possible example

One entity in an EDN file:

;; examples/todo/schemas.edn
{:todo [:map
        [:id :int]
        [:title [:string {:min 1 :max 60}]]
        [:done :boolean]
        [:priority [:enum "low" "medium" "high"]]
        [:created_at :string]]}

clojure -M:run -s examples/todo/schemas.edn -p 3000 --seed 42
# or: bb mock-server -s examples/todo/schemas.edn -p 3000 --seed 42

curl localhost:3000/todos
curl "localhost:3000/todos?done=false&priority=high"
curl -X POST localhost:3000/todos -H "Content-Type: application/json" \
  -d '{"title":"Write the announcement","done":false,"priority":"high"}'
# 201, and the server added "id": 6 and "created_at"
curl -X PATCH localhost:3000/todos/6 -H "Content-Type: application/json" -d '{"done":true}'
curl -X POST localhost:3000/todos -H "Content-Type: application/json" -d '{"title":"","priority":"urgent"}'
# 400 {"error":"validation failed","errors":{"done":["missing required key"],
#      "title":["should be at least 1 character"],
#      "priority":["should be either \"low\", \"medium\" or \"high\""]}}

That gives you GET/POST /todos and GET/PUT/PATCH/DELETE /todos/:id. There are bigger examples in the repo: a three-entity blog API in Malli and a shop API written in plain clojure.spec.

What it does

  • Schemas in: Malli from an .edn file, a .clj file, or an ns/var; or clojure.spec from a namespace or file. Entities refer to each other by keyword ([:address :address]), and recursive ones with [:ref :comment].

  • Data out: records are generated with malli.generator (so test.check underneath). --seed 42 gives the same data every time, so a team can share one command line and see identical records. A few field names get nicer values (email becomes an @example.com address, created_at an ISO timestamp), and you can add your own overrides.

  • State: an atom. POST, PUT, PATCH (deep merge) and DELETE work and persist until you restart. Every write is re-validated against the schema.

  • Validation: bad input gets a 400 with Malli's humanized errors. Ids and created_at/updated_at are filled in for you; other missing required fields are rejected rather than invented.

  • Extras: equality filters including nested paths (?address.city=Leeds), limit/offset, CORS headers, and GET /_schemas to see what it understood.

How it's built

Reitit for routing, Ring + Jetty for serving, jsonista for JSON, babashka.cli for the arguments, Malli doing most of the work. The pipeline is import, register, generate, store, serve, and each step is one small namespace.

The spec support is a one-way converter to Malli forms, so everything after import only deals with Malli. The converter handles the common cases (s/keys with -un keys, s/and, s/or, s/nilable, s/coll-of, s/map-of, s/int-in, s/double-in, enum sets, regex predicates, a few others). Anything it can't translate becomes :any and prints a warning on startup rather than failing.

Size

folderfileslinescode lines*
src/ (Clojure)7666586
test/2161141

* excluding blank and comment-only lines. 11 tests, 52 assertions. They call the Ring handler directly and include a run of both bigger examples. There are also user docs and a short developer guide under docs/.

Limitations (please read before trying it)

  • JVM only. bb mock-server -s schemas.edn -p 3000 works, but Babashka is only the launcher: Jetty and Reitit don't run under Babashka, so the task shells out to the Clojure CLI and the server runs on the JVM. A pure-bb version would need http-kit and a different router.

  • No referential integrity. Relationships are embedded copies or plain foreign-key fields. Generated foreign keys are random unless you constrain them (the examples use [:int {:min 1 :max 5}]), and deleting a record doesn't touch anything that mentions it.

  • In memory only. Nothing survives a restart. That's deliberate for fixtures, but it's a limit.

  • Partial spec coverage. Regex ops (s/cat, s/*), s/merge, multi-specs and arbitrary predicate functions fall back to :any.

  • Filtering is basic. Equality only. No sorting or ranges yet.

  • Rough edges I know about: integer id allocation isn't atomic, so two simultaneous POSTs can occasionally clash with a 409; non-numeric limit/offset give a 500; unknown JSON fields are silently dropped. They're all listed in docs/devel/design-notes.md.

  • Custom value overrides are only available when you start it from code (golem.app/seed-db!), not from the command line.

  • Young project: Clojure 1.12, Malli 0.16.4, tested on one machine (Windows 11, JDK 25, Babashka 1.13.229).

Why not X?

There are good tools in this space already:

  • moclojer is the closest Clojure project. You write each endpoint and its canned response by hand in YAML or EDN (or import OpenAPI or Postman), and it replays them. It's a good fit when you want exact, hand-written responses. As far as I can tell from its README it doesn't generate data from schemas or keep state between requests, which is the gap golem aims at.

  • Prism and open-api-mocker mock from an OpenAPI document, and json-server serves a JSON file you maintain. If your contract already lives in OpenAPI, use those.

golem is for when your source of truth is already Malli or spec in a Clojure codebase and you'd like the mock to follow it, with generated, stateful data, without writing a second description. I looked for an existing Clojure project that does this and didn't find one, but I may well have missed something, so please point me at it if you know of one.

Feedback

I'd particularly like to hear:

  • which spec forms you use that should convert and don't

  • whether relationships (generating real foreign keys from seeded ids) matter enough to build next

  • whether anyone would use this from Babashka alone, which would justify the http-kit rewrite

Issues and PRs welcome. Thanks for reading.


r/Clojure • • 10d ago

Making Simple Faster - Chris Nuernberger (Clojure/Conj 2026)

Thumbnail
youtube.com
37 Upvotes

r/Clojure • • 10d ago

Logging in Clojure today: Timbre, Telemere, mulog or tools.logging?

38 Upvotes

Clojure has more logging choices than it used to. Telemere, from the author of Timbre, is now past 1.0, and mulog is built around structured events.

So, for a new project today:

  • Timbre, Telemere, mulog, tools.logging over a Java logger, or something else?

  • If you moved from Timbre to Telemere, was it worth it?

  • Is anyone still logging plain text lines, or is it all structured events now?