A History of Clojure (2020) [pdf]
download.clojure.org
download.clojure.org
Easier to browse list: https://www.goodreads.com/list/show/137472.Rich_Hickey_s_Clo...
I find it interesting he includes Mozart/Oz (CTM). It'd be great to see more ideas from that language coming to Clojure.
Also Norvig's AIMA. Clojure could be well positioned for neuro-symbolic AI. That's somehow connected to Anglican, discussed in the History of Clojure article.
It looks interesting (though tbh I barely understand what it does.. it's borderline technobable to me) but I haven't been able to find it used anywhere on Github. It's also gotten zero updates since 2018
Doesn't mean it's not a hidden gem... I would have said something similar about Missionary as well
But it is probably too expressive, and therefore too slow, for most practical inference problems.
E.g. I’m not aware of any large framework like Rails or Phoenix. Is this something that is missing and yet-to-come, or there is no need for that?
How does this affect job search, are Clojure jobs less about SAAS/CRUD apps? Does each place build their own custom tooling?
As for SaaS apps, Clojure is a really good fit, because of ClojureScript. You can have a large part of your code as .cljc files, and compile both to JVM and to JavaScript in the browser. I found this is an incredible advantage, enabling a single founder like me to write and maintain a complex SaaS.
Also ClojureScript doesn't do WebAssembly.
It's a bit ambiguous what you mean with "do", but you can definitely use WebAssembly modules in ClojureScript just like you can in JavaScript.
I'm not familiar with Blazor or C# so maybe I'm missing something obvious here.
But I can tell you that most of my model (business logic) code is written in Clojure and compiles to both JVM and ClojureScript. In other words, I use the same code on the server and on the client. I also use EDN (meaning Clojure) as the serialization format between them, so I avoid serializing to something non-native. All this buys a lot of incremental improvement.
ClojureScript gets compiled using Google Closure compiler in "advanced" compilation mode — for those who might not know, this is not a "minifier", it's a whole-program transformer which does renaming and dead code elimination. The result is highly optimized JavaScript. I guess that's why there isn't much excitement about WebAssembly in Clojure circles — the current state of affairs is really good enough. In my experience (complex SaaS app), DOM operations are a performance bottleneck, not ClojureScript.
- Incredibly slow
- Hosted on the JVM, so you're going to be dealing with Java eventually
- No automatic tail call optimization because of the limitations of the JVM, so it feels like you're writing a mess of macros rather than real functional code
Huh? Clojure is one of the fastest dynamic languages. It's not intended to replace C++ or Rust.
> - Hosted on the JVM, so you're going to be dealing with Java eventually
In the real world this is a blessing since there are a lot of useful Java libraries out there.
> - No automatic tail call optimization because of the limitations of the JVM, so it feels like you're writing a mess of macros rather than real functional code
How did you come to this conclusion? Lack of automatic TCO doesn't mean you have to write macros, and most people in the Clojure community will tell you to prefer functions over macros unless it's absolutely necessary.
Almost as fast as Java, and for performance critic processes 99.9% of the time we bump on infrastructure performance problem BEFORE hitting the wall with Clojure (see https://clojure-goes-fast.com/blog/ for tips and tooling about performance)
> - Hosted on the JVM, so you're going to be dealing with Java eventually
For me it's a major selling point: JVM is battle tested and a wonder of engineering. The Java ecosystem richness is incredible (see tooling above for monitoring and profiling for an example). And the platform is constantly moving forward (see latest JDK with virtual threads, generational ZGC, etc.). And of course GraalVM... (https://www.graalvm.org)
> - No automatic tail call optimization because of the limitations of the JVM, so it feels like you're writing a mess of macros rather than real functional code
Never have been a problem and I don't see the point with macros, and code we write looks _very_ functional...
This is all true.
That said, the way I can't help but feel is: keep that entire galaxy of insane bloat two and a half million miles away from me please. :p
However, I want to point out that sometimes Java can peak its head out. If you rely on Java tooling you will also likely need to have some idea of how Clojure implements things in Java.
So while Java gives us access to a great variety of tools and libraries, heavy reliance on the host can make things a bit more difficult, especially for new programmers.
> 9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.
"Just use a map" [0]
I know nobody believes me when I say this, but I really mean it.
If you want to look at libraries where some people have settled, here are our _opinionated_ takes on libraries that we use on almost every project:
- HTTP: Ring is the de facto way to manage HTTP request (see https://github.com/ring-clojure/ring/wiki/Concepts) supplemented with various "Middlewares" for web-related concerns (security, logging, content encoding, etc. see https://github.com/ring-clojure/ring/wiki/Standard-middlewar...). Jetty and Aleph are common web servers (and https://github.com/clj-commons/aleph) that implement Ring interface.
- Routing: Reitit (https://github.com/metosin/reitit)
- Single-Page App: shadow-cljs for the build concerns (https://github.com/thheller/shadow-cljs), Reagent with Re-frame for complex/large app (https://reagent-project.github.io and https://github.com/day8/re-frame). Even if we now prefer using HTMX (https://htmx.org) and server-side rendering (Hiccup way of manipulating HTML is just amazing, https://github.com/weavejester/hiccup).
- Schema management: Malli (https://github.com/metosin/malli)
- Lifecycle management: Mount, Integrant or Component (https://github.com/tolitius/mount https://github.com/weavejester/integrant and https://github.com/stuartsierra/component)
- Config management: Aero (https://github.com/juxt/aero) and environ (https://github.com/weavejester/environ)
- Log: μ/log (https://github.com/BrunoBonacci/mulog)
- Time: https://github.com/juxt/tick
- Testing: https://clojure.github.io/clojure/clojure.test-api.html and Kaocha for the runner (https://github.com/lambdaisland/kaocha).
- Package and project management: tools.deps is simple and powerful (https://clojure.org/guides/deps_and_cli)
For infrastructure stuff (PostgreSQL, Keycloak, Solr, Kafka, etc.), just wrapping the underlying Java library or driver is often enough, and there are lots of wrappers for easing the integration. And we implement Hexagonal architecture style to put all of that in place.
Don't be afraid a libraries not moving a lot recently, it's a sign that the library is mature and battle-tested. Clojure is a joy to use every day :)
And writing your own Lisp in your favourite programming language is super fun btw. Highly recommended.