First – a bit of background. When I first started learning programming, I started with a course in high school that focused on Java. From there, I decided I wanted to work for a start-up and I had to learn python (I was naive). I started playing with Python and it just felt right – at first. I spent some more time with it and started to realize that I needed something more. Here’s a brief list of the reasons why I switched.
Python is a dynamic language. There’s a massive list of Pros and Cons for this, but I’ll highlight a few of my concerns.
- It’s easy to introduce bugs on uncommon code paths that would be much more obvious in a compiled language.
- The performance of an interpreted language is almost always slower than a compiled language.
Those things aside, I LOVED being able to quickly run code with a fast turn around time. When testing, I didn’t have to worry about compiling anything and, when I was developing with Flask, tools like Live-Reload were things I didn’t want to give up.
With Clojure, I found that I could have the benefits of an Interpreted Language and the benefits of a compiled language, too! By leveraging Clojure’s REPL, I’m able to quickly test code before/while/after I write it. You’re able to switch into your Clojure codes namespace and test any functions you’ve written, as well as get the source code for any specific function, or check the docs for any function too! If you’re not using the REPL when you’re writing Clojure, you really should give it a try! If you’re using Leinengen, you can run
lein repl from your project directory!
With Clojure, you compile down to Java Byte Code when you run your application or library. You get the benefits and performance optimizations of a compiled language, but can treat it like an interpreted language when developing. It’s great!
Classes Vs Data
When I moved from Java to Python, I fell in love with Mutable Dictionaries. I became very intimate with the dictionary API and defaulted to using them instead of classes because they often met my needs on their own and honestly, the “implied self parameter” on python methods turned me off. Dictionaries are basically just a map data structure.
When I learned about Clojure, I was baffled by their lack of classes, but felt liberated by the thought of only writing functions in namespaces. I decided to give it a try and immediately started thinking of Dictionaries in Python and how I didn’t enjoy writing classes. With Clojure, I’m able to focus on what the data looks like, and not on how an object is expected to act (What’s an instance of a class but a hash-map with some namespaced functions anyways?).
Immutable Data & Stateless Code
Like most now-functional programmers, I had THE incident. I had a class with several methods, but only two were particularly important. Both methods were getters, but the 1st method updated the value that was returned by the 2nd. This was extremely misleading when the code executed. In fact, almost all of the bugs with this code revolved around this theme. I didn’t know what to do and I thought this was the expected way to write code. I later read a great post on immutable data and tried writing my python code this way. This worked great – until I started working with other developers.
With Clojure, you have to fight to use mutable data structures (that’s not to say it’s impossible, it’s just not the default). More importantly, if you’re working with Clojure developers, chances are they’re very familiar with the benefits of immutable data. I say “fight” because you do have to put forth some effort to do it, but you often don’t really want to.
Don’t get me wrong, the Python community is great. Probably one of the best ones out there, actually. By comparison, Clojure’s community is very small. As you know, the communities are the groups of people responsible for building libraries for the language to use and helping people who get stuck with strange error messages or confusing domain problems. In terms of libraries, Clojure has extremely nice Java Interoperability (Clojure can call Java code directly from itself). This means that Clojure has access to ALL Java libraries and any clojure libraries as well. That’s a vast amount of libraries!
The support and documentation for most Clojure things pales in comparison to python, it’s true, but what I have noticed is that it matters where it counts. Clojure’s core API is relatively lean and extremely well documented. Additionally, the Clojure community didn’t experience the weird split that Pythonistas had with Python2 and Python3 (I’d imagine this is worked out by now, but I haven’t kept up with Python since I stopped writing it for anything more than scripts).
No __init__.py or __setup__.py
A shitty reason to dislike python, but these both irritated me a LOT.
For those who don’t know, and __init__.py file is used to declare a directory as a python module, while a __setup__.py is used to define how other scripts should interact with yours. That being said, neither of these have to do just that. In fact, I feel like the expectations for what each should do is extremely vague and troublesome. Some people prefer to import modules into their __init__.py or even add convenience functions there, too. It’s often easy to overlook these files, but if you can’t find the definition for a particular function or module, check the __init__.py
As for __setup__.py, you should probably just call the
setup function from
distutils.core. But, you can do more in that file – so much more! In fact, the actual documentation on this is pretty vague on what all should exist in a setup file, and can be found here.
In Clojure, everything is handled in a nice
project.clj file, if you’re using Leinengen. That being said, you can also use a nice, structured
.gradle file, if that’s more your cup of tea. A
project.clj file is defined similar to a
To sum everything up, I switched predominantly because I wanted to speed and comfort of the JVM, but wanted a language that supported functional programming paradigms. Which do you prefer – Python or Clojure or something else? Comment below and let me know!