loading...

Why Clojure?

kspeakman profile image Kasey Speakman ・3 min read

The language is the compiler. What could go wrong?

If you are braced for a hard sell of Clojure then be at ease. Instead I am going to document what interests me in the language. And why I am starting to use it in a hobby project.

Ideas

I was initially attracted to Clojure because it is a Lisp that embraces functional programming. You can probably find a million articles about the benefits of functional programming (immutability and pure functions) so I won't rehash that. But why Lisp?

For me it is the malleability. The language is the compiler. I have the power to add new capabilities to the language for my problem space, without waiting on language developers. For example, other programming paradigms -- including object oriented and functional -- have been implemented on top of Lisp. This malleability wasn't a feature on the backlog that the language developers had to spend millions of man hours to code. It is due to the nature of Lisp code being just lists of data. I probably will not be adding any fundamentally new features to the language itself, but this also means that my everyday business code has a lot of capability at its disposal.

Lofty ideas only get me so far. I also need practical reasons to undertake such an time investment.

Dynamism

For many years I have used statically typed languages. I like types. They bring order to the chaotic universe. But sometimes types can become a little tyrannical.

I usually write our architectural plumbing code, because I am old and I didn't repeat my first year's experience too many times and the team entrusts it to me. In this kind of code I use a "context" type. It keeps settings and operation details (the user, their organization, and so on). This chunk of data gets transformed multiple times (ex. before/after user auth) as it makes its way through the system. At some point, I realized that I was spending a lot of time doing Type Tetris rather than running the plumbing. And now I cannot unsee that, and I notice it in other places as well.

There is a lot to be said for finding joy in solving the problem rather than finding joy in the tools used in solving the problem. As I get further in my career, I keep trending toward the first one.

Precise types

Hang on, but you just said...

I like types. They are quite useful. For example, at the borders of a system to define contracts between other systems. So I was put off by the idea of going to a completely dynamic language. Then in my research I ran across a fascinating article called Typed Lisp, A Primer. I am not very familiar with Lisp, so some of it went over my head. But the main message I received was that types in Lisp are just functions which check qualities about the data.

That means I can opt into types. It also means that types can be far more precise than what we get with statically typed languages. For example, I can define a type that is not just an integer, but an integer in a specific range. And I can require incoming data to conform to that by declaration.

So I still get to have types where I want them and in a more precise form. And I can have dynamism where it benefits me.

Clojure's typing library is called Spec.

Conclusion

The laws of the universe dictate that there is no perfect tool, so I am confident that I will discover trade-offs in my journey through Clojure. But I find it incredibly useful to see problems from different perspectives. And I expect that learning Clojure will add some new lenses for me to look through.

I'll try to keep you posted on what I learn.

Posted on by:

kspeakman profile

Kasey Speakman

@kspeakman

collector of ideas. no one of consequence.

Discussion

markdown guide
 

At least in Python, I find that the "opt-in to types" model doesn't work well. For example, libraries like Mongoengine are so dynamic that the returned type effectively depends on a dict. Dicts can be too (TypedDict), sure, but it doesn't happen in practise.

So why not do it the other way around? Haskell has Data.Dynamic.

 

Thanks for the comment and suggestion.

I believe Clojure's coding model is rather different than python's and can manage opt-in typing pretty well, from what I have seen. (We shall see.) It also resonates with what I do in F#. F# is statically typed but as with most languages, types match the underlying machine, not precise enough to exactly match the parameters of specific use cases. So I filter all requests through an extra validation function before proceeding, similar to Clojure's approach to typing.

The other alternative is to create a wrapping type to represent the more specific version of data, and have that type's constructor block creation unless data matches constraints. However, I find that approach to have a lot of overhead in dealing with the wrapping type. So I do not use it.

Regarding Haskell. Even if I use dynamic myself, it seems unlikely (from some prior research) that libraries I want to use will. Plus it seems to be common for some of the major libraries and samples to code on top of category theory abstractions. So any new person I bring on must first back-fill theoretical math knowledge before they can do meaningful work. (And memorize whatever custom operators the library chose to use.) I am all for them learning the math if they want, but it feels too much to require as a first step. (Last few hires had no prior experience, and we like it that way.)

 

Interesting article. I too am a huge fan of types and static typechecking. I dislike Python and JS for that reason. But Clojure has really piqued my interest. I haven't tried it yet and I still have my doubts regarding the dynamic nature of it. I will probably try it once I have time, I'm somewhat looking forward to it.

 

This talk has a pretty compelling explanation about types with spec. The link starts 9 minutes in where he begins to address typing. Quick background: he explains "systemic generality" earlier in the video. But it is basically instead of specific types, in Clojure you use maps (dictionaries with named keys) and vectors (lists) for everything.

 

I've started with clojurescript and loving it. Just wish had more time to really test it out with a serious app.