r/Clojure • u/yogthos • 1d ago
Lambda performance comparison of running different Clojure dialects
r/Clojure • u/yogthos • 1d ago
r/Clojure • u/yogthos • 2d ago
r/Clojure • u/yogthos • 2d ago
r/Clojure • u/alexdmiller • 3d ago
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 • u/alandipert • 3d ago
r/Clojure • u/TTalkIM • 3d ago
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 • u/WraithGlade • 3d ago
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 • u/MagnusSedlacek • 4d ago
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 • u/BrunoBonacci • 4d ago
THIS IS AN ONLINE EVENT
[Connection details will be shared 1h before the start time]
The London Clojurians are happy to present:
Title: Programming a business to improve itself
Speaker: Christian Weilbach
Time: 2026-11-17 @ 18:30 (London time)
Local time: click here for local time
RSVP: https://www.meetup.com/london-clojurians/events/317380055/
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:
And many individual sponsors
RSVP: https://www.meetup.com/london-clojurians/events/317380055/
r/Clojure • u/abogoyavlensky • 4d ago
r/Clojure • u/yogthos • 4d ago
r/Clojure • u/alexdmiller • 5d ago
r/Clojure • u/daveliepmann • 5d ago
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 • u/alexdmiller • 6d ago
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 • u/alexdmiller • 6d ago
r/Clojure • u/yogthos • 6d ago
r/Clojure • u/cjmurrr • 6d ago
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 • u/alexdmiller • 9d ago
r/Clojure • u/thijscreemers • 9d ago
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.
Release notes: https://wagoe.org/docs/blog/v1-1-1.html
What it is and why: https://wagoe.org/docs/blog/wagoe-1-0-ship-your-clojure-app.html
Stability and tiers: https://wagoe.org/docs/stability.html
Happy to answer anything about the authorization model, or about why a framework at all in Clojure.
r/Clojure • u/cjmurrr • 9d ago
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 • u/fadrian314159 • 9d ago
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)
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.
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.
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.
| folder | files | lines | code lines* |
|---|---|---|---|
src/ (Clojure) | 7 | 666 | 586 |
test/ | 2 | 161 | 141 |
* 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/.
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).
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.
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 • u/alexdmiller • 10d ago
r/Clojure • u/cjmurrr • 10d ago
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?