Data Modeling in Clojure

I’ve recently started a deep dive into the world of Clojure. I’ve had a long fascination with functional programming, and its many promises, but had steered clear of Clojure because of the JVM (shudders).

One of the more abrupt changes to my way of thinking about programming comes via Clojure’s data structures. I’ve spent plenty of time with languages like Ruby, Python, C#, etc.; languages that not only allow for an OOP-style of programming, but almost demand it. Even in a language as flexible as Python, everything is an object, including functions. Pretty quickly, you learn to think of representation of data through the lens of classes or dataclasses.

Clojure very quickly disabuses you of the notion that classes are at all necesary for creating meaningful models of the data that you’re working with. The best you can do for encapsulating data is a map (dict in Python, hash in Ruby, etc.) Even Go (a self-professed non-OOP language) gives you structs and methods, and Elixir (functional!) provides you with a struct type. Granted, it’s little more than a wrapper around Elixir’s map data structure, but still - it provides some familiarity and comfort, no?

Clojure doesn’t care. And why should it? We’ve long since adopted JSON as the norm for passing around data via our web payloads, and there’s little more to it than the most primitive of types, with arrays and key-value mappings being the most complex data types you’ll find. Redis relies on a structures not too dissimilar from what you’ll find with JSON.

Instead of classes, you have namespaces. Instead of methods (init or otherwise), you have functions. And instead of classes, you have maps, mapping any given number of keys to their corresponding values. While initially unnerving, I’ve found this leads to more accessible code, and considerably less time spent on modeling. Data structures in Clojure (as with most functional languages) are immutable, so you have to spend less time thinking about how to model complex hierarchies, and get to spend more time refining the abstractions tied to your functions that act on your data structures.

It’s a little scary, but vey refreshing.

Written by

Leo Rubiano

Reader, programmer, traveler. Experienced back-end dev proficient with Python, Go, Elixir, Ecto, and Postgres.