Why not Clojure?

When people ask me “Why Clojure?”, I sometime answer: “Why not?”

At which point, some people might try to come up with reasons:

  • It doesn’t have static types
  • It isn’t popular
  • It has slow startups
  • It uses a lot of memory
  • It’s hard to hire developers for it
  • It doesn’t have enough Clojure based libraries and frameworks (i.e. Not interop based)
  • The Lisp syntax is hard to read and unfamiliar
  • The JVM is too bulky
  • It’s hard to write ultra performant algos and math
  • Etc.

And generally I retort:

I find it more fun to write programs using Clojure, it brings me joy and makes me productive. None of the reasons you provided have prevented me from delivering the expected results, so Why Not?

Per another thread here, I’ll say: if you have a commodity problem, then you probably want a commodity solution – which Clojure is not.

2 Likes

It could be countless, and highly subjective reasons but I’ve thought about this a lot and have some ideas at least at the individual, more personal level.

  • One of my friend’s choices for going with Python\Django: The automatic admin UI is a huge time-saver for getting a feature out that staff can work on. I don’t think there’s a Clojure adjacent as of now which includes a solid backend and frontend experience for scaffolding an app. For those unfamiliar: You define your model then Django can generate the admin form pages for it including form UI and validation and related backend CRUD.
  • Learning Clojure does require you to change the way you approach problems. That’s hard to let go.
  • Hosting for a Clojure app is not quite as cheap or as easy to setup as say PHP
  • It’s not already on your system like Python is on OS X and some Linux distros
  • It’s a little more complex to run than say JS, Ruby, Java, or Python given that it’s a hosted language. Though the Clj tool goes a long way towards fixing that.
  • Clojure is not taught in most schools as far as I know, so in most cases it requires a choice on people’s part to spend the time to learn it.
  • The simplicity Clojure brings is hard to communicate because when it’s done right it’s intentionally underwhelming [1]
  • You don’t find as extensive docs for Clojure projects as you do a lot of major Python or Ruby libs. [2]
  • I theorize people love finding quantifiable facts (# of bugs on avg, static types, startup time, hiring etc…) that they can use to justify their subjective choices. [3]
  • I also theorize the more excited you are about something, the more resistant your peers are to trying it. Few want to believe peers know something they don’t or have an advantage over them [4]
  • Because it’s not mainstream people want to assume it’s for a good reason, or may feel it’s too risky.
  • Sunk cost fallacy (Java is what I already know so Java is what I should use)

[1] That sense of addictive accomplishment working on a complex problem isn’t as apparent in Clojure than when you finally wrap your head around a complex Gang-of-Four pattern, or finally learning how that mission-critical, under-documented system, built around a cutting-edge at-the-time Postgres plugin, that a co-worker just barely got done before leaving the company developed. Where as in Clojure often you feel like, “Meh. It’s a function that takes a hash-map and returns a seq of hash-maps. I never have to think or worry about this ever again.”

[2] Something that took getting used to when transitioning. From my Python, especially Django experience, you DREAD hitting the View Source link to the github repo. You know if you do, you’ll be chasing down so many arbitrary class definitions to find that one class that affects the behavior you wanted to learn more about.

In Clojure, viewing source can become your first reaction to learning functions. You realize you don’t need a book of docs for every project because most of your code is just transforming arguments and finally sending it somewhere with side-effects. Projects like Django and most Ruby projects I’ve explored really like to invent a lot of terminology between the code required to solve the problem and the domain problem you’re solving.

“No, you can’t just transform a hash-map of request data into a hash-map of response data. You need this specialized View class which receives an HttpRequest instance, and sub-classes the TemplateView class and uses these lifecycle methods to manipulate these specific attributes so you can return an HttpResponse instance. But don’t worry. We’ve generated docs for every class, subclass, method, and attribute.”

[3] In reality, I feel it’s a lot like choosing a color for a painting. It’s usually an informed choice, layered with expectations, but it usually comes down to mostly liking it.

[4] When I first met someone who used Clojure, I didn’t react with bewilderment and curiosity. I thought it looked weird and unreadable with all those parenthesis and believed at the time that a language like Python or Ruby with its cleaner syntax would make things more maintainable in the future. Oh what a fool I was!

3 Likes

I get my kicks solving hard problems, but OO design patterns never qualify as such. Tbh, for me they’re just obtuse workarounds needed to cope with the lack of expressive power in Java / C++, etc, and they tend to obfuscate any domain logic.

4 Likes

You could say that about any language or technology. I would say that same thing about Javascript and OOP. Even though I rarely use it anymore, my most productive language is still Java. It pains me to the core to say that. People have plenty of reasons for hating all of those and that’s fine. Use what works for you. There’s nothing wrong with choosing a language or paradigm that fits you better and you’re more productive with.

I will say this, though. The fact that Clojure is a Lisp is probably the main knock against it for people. I had a coworker who went to MIT in the 90s. They hated using Lisp so much that by the end of their freshman year decided to switch majors and teach themselves to program in their spare time rather than spend 3 more years using it. Sad truth is that Clojure could quite possibly have been in the position that Kotlin is now if it wasn’t a Lisp.

My interest in Clojure is that it’s an interesting experiment. A Lisp, but more like Racket, immutable data structures built in, etc. I think a lot of thought went into why it does things the way it does. I was similarly interested in Rust until I tried to use threads with it, which was probably the worst experience I’ve ever had as a programmer.

That’s fair. It was a poor example, but what about understanding the source of a codebase that was intimidating at first?

An example for me was learning specific parts of Node JS’s core. There are so many variables, callbacks, and handlers defined in the callbacks for different async operations, that it’s hard to really understand the intent by looking at it. Then after more rereads and looking up docs I got that “Aha! I see what it’s doing now.” feeling. Where as with Clojure, intent is usually pretty clear and the code tends to be pretty concise so I don’t get that spike of making it uphill.

I’ve been coming across this statement a lot recently, and it just doesn’t compute. Clojure is, in its heart of hearts, a hosted language. It fully embraces interop. What’s the basis for saying we should eschew that nature?

If I understand correctly, this is related to Graal native images being unable to load classes dynamically. If the libraries are pure Clojure, you can interpret them (with some caveats) with SCI, so they could be made to work with Babashka. Loading JVM bytecode, however, is a no-go.

(again, I might be completely off base, but I think this is what @didibus was referring to)

I personally couldn’t, because Clojure is currently the language I enjoy most and am most productive in, but you’re right that others might have different preferences, and that was my point :stuck_out_tongue:

Basically, I find the question of “Why?” and “Why Not?” in programming languages kind of pointless honestly. The only why that matters is: “because I wanted too”. As long as you can deliver the expected results at the expected cost/time horizon, then it was a good choice.

So what I’m trying to say is, each developer should consider what they like best, what style they are most effective in, most engaged, most motivated by, etc. This will guide you the your language of choice. After that, mastering that language, and starting to work on more fundamental aspects and specialize in certain problem areas is probably a much better time investment then to continue to look for the “best language”.

One thing that is a good investment no matter the discipline is to always push yourself and work on things out of your comfort zone as well. I like Clojure for that, because it has so many concepts that one can explore that it seems to always challenge me and keep me learning. That’s generally why I like it, and that’s why I tell others they should check it out.

It might have, but I probably wouldn’t use it if that was the case. I’m happy it is a Lisp personally, wouldn’t want it any other way.

To clarify, I wasn’t necessarily listing Why not? reasons that I personally agree with or feel they are good reasons against the use of Clojure. So I mostly listed things I have heard others bring up. I actually agree with you, being hosted is a positive to me, don’t re-invent the wheel, when Java does well just use it directly.

If it wasn’t a Lisp, it wouldn’t be Clojure. Kotlin is Kotlin. I like Kotlin, I’d probably be moderately happy using it if I couldn’t use Clojure. As I seem to have been saying quite a lot recently, going mainstream is a non-goal for Clojure – it’s designed by experienced developers for experienced developers, who’ve had enough of certain kinds of pain caused by other languages, that want a “high-leverage” tool, to solve interesting problems. It’s not for everyone. By design.

I can totally understand that a lot of developers will try it – sometimes really get deep into it – and then move on, for myriad reasons.

As for justifying my opinions, they’re based on 35 years of software development, in dozens of programming languages, along with learning dozens of additional languages over the decades, as well as serving on an ANSI Standards Committee for eight years (C++), producing one of the first ANSI-validated C compiler systems, and my PhD work on the design and implementation of functional programming languages (back in the early '80s). I like to think I’m pretty well-informed on language design :slight_smile:

3 Likes

Right - not every idea, business, meme or even programming language need have world domination as a goal.

In one sense however it’s a bit of a shame, as probably not 1 in 10 devs who come to enjoy using Clojure are likely to be able to use it at work. Totally made up figure of course, but the odds are that if you enjoy javascript or python and are even half way competent you’ll probably find a job using it. Not so with Clojure, which could be a motivational minus for some.

1 Like

Yeah, that was my problem with APL and Prolog (back in early '80s and early '90s respectively :slight_smile: ).

2 Likes

I have actually written Prolog on a job many (many) years ago. I was employed as a research assistant rather than a programmer at the time, and had absolutely no idea what I was doing. I think I got things to work, more or less.

Some tweets from Timothy Baldridge:


1 Like

I wouldn’t necessarily word it that way. Hickey wanted a language to use for high concurrency applications and made it a Lisp because he likes Lisp. Like most language developers, he wrote the language that he, personally, wanted to use. He didn’t sit down and think, “Experienced developers are having a rough go of it, how can I fix that?”

Node has a similar back story. Dahl wanted a language that could handle a large number of simultaneous connections. He went with Javascript because it has non-blocking I/O built into it. And what better way to avoid the pitfall of thread per connection than using a language that doesn’t even have the concept of a thread in it?

I will say, the more I use different Lisps (Clojure, CL, Scheme, Racket), the more they feel like Javascript to me. I realize it’s actually the other way around and I’m only wording it that way because I’m more accustomed to JS, but I like using different languages instead of the same one all the time and it’s kind of bummed me out a little that it feels like I’m still using JS when I code in Lisps.

Stuart Halloway would tho’ https://twitter.com/stuarthalloway/status/1249772079068700674

#Clojure was designed by and for, and continues to appeal to, experienced developers who want keen tools to solve interesting problems.

1 Like

Rich Hickey wouldn’t. From https://www.linuxjournal.com/article/10708

I discovered Lisp after ten years of C++ and said to myself, “What have I been doing with my life?” I realized it was just much more productive for me. I fell in love with it right away. Basically, I said to myself, “At some point in my life, this is really what I want to be doing.” I spent several years subsequent to that continuing to do my commercial work in Java and C#, but all the while hoping at some point to be able to get Lisp into the mix. That’s what drove me to doing Clojure, because I saw that either .NET or the JVM were requirements for all the customers I was encountering. Lisp really couldn’t reach those platforms, so I decided to make a Lisp that could.

I’ll assert that Stu’s words are still accurate: Rich Hickey is an experienced developer – he designed Clojure for himself (and people “like” him). Since the early days, the folks involved in the ongoing design work of Clojure have all been experienced developers, focused on the tools they need/want. And nearly all of Clojure’s early adopters were experienced developers, looking for better tools to help them solve non-mainstream problems.

When I started using Clojure a decade ago I was an outlier because, although I was a very experienced developer, I wanted to use it to solve fairly mainstream problems (and I gave a talk at Clojure/West 2012 about “Doing Boring Stuff with an Exciting Language”). That’s how I ended up maintaining the JDBC wrapper in Contrib: almost no one else was using Clojure for “boring” stuff like relational database work! At the time I was genuinely shocked that people were not using Clojure in those sorts of mainstream problem spaces.

Looking at the Clojure community and ecosystem today, it’s grown to the point where it can seem like “just another JVM language” and, of course, even clojure.org describes Clojure as a “general-purpose programming language” – which somewhat obscures just how specialized Clojure really is. And for several years the main sector of use for Clojure has been “web applications” which tends to make people want to compare it to a lot of other languages in that very crowded space. And those comparisons, on the surface, will lead a lot of people to pick something other than Clojure (for many perfectly good reasons).

(I’m trying to tie this discussion back to the original topic by saying that!)

2 Likes

That can also be said of C++ in the 80s, Java in the 90s, and Node in the 2000’s. So aren’t those languages also “by and for experienced developers”? Also tying back into the original topic, they’re really all the same and you should pick the tool that works best for you and makes you more productive. :slight_smile:

The only languages I can think of off the top of my head that wouldn’t fall into that category would be BASIC and Python. They were designed with the idea of making them more accessible for beginners.

I’ll agree on C++, especially as someone who spent eight years on the ANSI C++ Standards Committee – three years of which I was its secretary! (I was also the UK’s “Principle Expert” on the ISO committee for much of that time)

One of Java’s design goals was to be simple and familiar – and it is very suitable for low-to-medium skilled developers who need guard rails and a language that helps them avoid many basic mistakes. It’s why it’s been so successful in the enterprise – with vast armies of mediocre developers churning out tens of thousands of lines of straightforward code, propped up by their IDEs generating a lot of boilerplate.

Node.js doesn’t really belong in the same category: it’s a platform runtime for an existing language, and that language was scrappily thrown together in a couple of weeks to provide Java-like syntax over a mix of OOP and Lisp thinking. I don’t think it’s even fair to say JavaScript was “designed” :slight_smile: (and looking over the design principles for Node.js itself, simplicity and pragmatism are frequently highlighted).

1 Like