Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

Challenge your functional programming abilities with Clojure & Leiningen

Next JVM languages to learn graph

In a recent survey of over 2100 software engineers, Clojure was selected 3rd after Scala and Groovy as the “next JVM language to learn”. Wait, what? Clojure, basically Lisp for the JVM, isn’t even in TIOBE’s top 100 programming languages–yet, 1 out of 8 Java developers want to learn it? Interesting…

This reminded me of a blog post that was written almost a year ago by RebelLabs Author Erkki Lindpere, about his vision on a OOP vs. FP debate and the composability of objects. This great, controversial post produced some great discussions, and although I recommend you going over them, they are not critical to understanding this article.

What Erkki said that got me thinking is this:

“I think most programmers today (including me) don’t really understand how to make this approach work for complete programs. I would love for the functional programming advocates to put more effort into explaining how to build complete programs (that contain GUIs, database interactions and whatnot) in a functional way.”

And this is exactly what I want to talk about today. Most of us have a solid background in programming object oriented software. Almost everything is an object in Java and you’re anything like me, and spend most of your day using Java and JVM, it inevitably left a mark and hardwired certain design patterns into your brain.

So let’s not start with full programs right away, let’s build something simpler first: how about we build a data structure in Clojure?

A data structure is a good option, because data structures are important, operations on them are normally described in an imperative fashion and the implementation can be small enough to figure it out in one go. I’ll pick Clojure in light its persistence and fiery community in the JVM world–if you need to refresh your memory you might want to look at The Adventurous Developer’s Guide to JVM Languages – Clojure”, but I’ll quickly review the necessary parts here as well.

Say hi to Clojure

Clojure is a dialect of Lisp that gets compiled for and run on the JVM. Clojure is a functional language, with a code-as-data approach, macros, software transactional memory and reactive agents for concurrency. Clojure is dynamically typed, which brings joy to half of the world while saddening another half. Also there’s an effort to get an optional type system for clojure, so don’t dismiss Clojure just because you’re a static typing fan.

Don’t worry if you’re not fluent in Clojure, we won’t go deep. Necessary constructs for us will be following:

;; evaluates the expression, parentheses are important 
(expression)
 
;; creates a named function called ‘name’ which takes param list as a param and evaluates the expression 
(defn name [param list]
         (expression optionally using params)) 
 
;; prefix notation
(+ 3 4) 
(zero? (mod 100 10)) 
(take-while neg? [-2 -1 0 1 2 3])

If you can guess an approximate meaning of these, you’re good. Otherwise, spend 10 minutes on this getting started guide, which will be useful anyway.
Now, let’s tackle a small problem using functional programming!

Creating a queue

This part was heavily inspired by a Reddit thread discussing the same topic. How do traditional concepts like encapsulation or inheritance convert into the functional world? Do we need them there at all?

The context of these questions is: how would you go to implement a queue in a functional programming language? The object-oriented paradigm was designed to answer this modeling question easily. Most of the things in the OO world are nouns (aka objects), so when designing something you extract nouns from a necessary functionality description and build your model around that. For a queue, you’ll take a list of nodes and make the parent queue object reference the head and the tail, and limit the operations so only a queue interface is exposed.

Functional programming works better when you focus on the verbs that describe possible actions and what, in general, is possible to do with the values. If we get a value that represents a queue, which operations will we carry on it?

First we need to construct a queue somehow, then there are two basic operations that are allowed: enqueueing an element and dequeueing it. Ok, ok, also peeking at the head of the queue without modifying the state. This is actually an answer to the question: how do you design a queue in a functional language?

You declare a module or namespace, or whatever concept your language uses to prevent you from polluting the general namespace with your functions and specify operations:

  • empty-queue
  • enqueue
  • dequeue
  • head / peek

Then, the implementation basically writes itself, seeing how many ways there are to create an empty queue value that is implemented by two lists. Now other functions must operate on a given queue value, so they take it as an argument. The problem statement didn’t specify that the implementation has to mutate data in-place, so we can peacefully return a new queue where the desired operation has already happened.

(def empty-queue [() ()])
(defn enqueue [[a b] x]
  [(cons x a) (concat b [x])])
 
(defn head [[_ b]]
  (first b))
 
(defn dequeue [[a b]]
  [(butlast a) (rest b)])

The code above is straightforward and trivial. Cons and concat are functions to manage lists; first, rest and butlast are as well and they mean exactly what they say: first returns the first element of a list, and rest returns all the rest of the list. This simple implementation is sufficient to use in a designed system and you can always revisit the implementation of these functions later.

Naturally, you can always go deeper into the language toolbelt and find concepts like protocols, closures, records or datatypes and produce something that resembles an OO solution that you’re accustomed to. However, remember that most of the problems that we deal can be expressed with a handful of verbs, which should map nicely into the function declarations. So keep it simple.

Getting a real app running

At this point we’ve tried our hand at modeling a small, well-defined problem in the functional style and the solutions we came up with are fairly comprehensible. Let’s try something closer to a real-life application.

One good thing is that for all mature languages, there are appropriate build tools that are great at providing you with a solution to a problem already solved by somebody else. Clojure project management is automated by Leiningen. Install that, and the easiest way to get to the Clojure REPL becomes: lein repl. As you can see on the image below, it does indeed produce a healthy REPL instance and you can immediately show off your functional programming skills or test if some Clojure construct works as expected.

clojure-repl

Now that is just a beginning; here’s how you create a command line application that reads some input and spits the output back.

To create a new project, run:

shelajev@shrimp ~/repo/tmp » lein new cmd-app
Generating a project called cmd-app based on the 'default' template.
To see other templates (app, lein plugin, etc), try `lein help new`.

Then you need to locate a file called core.clj and edit it a little. My core.clj looks like this:

(ns cmd_app.core
    (:gen-class :main true))
 
(defn greeting []
    (println "Hello beautiful world!")
    (println "Enter something: ")
    (let [phrase (read-line)]
        (println (str "Echo: " phrase)))
    (println "Ciao!"))
 
(defn -main [& args]
    (greeting))

I looked for a Leiningen template that will create a full command line application that parses arguments and then gives control to my code, but I failed to find one. So we’ll go with this simpler version, which starts, reads the input and serves as a great entry point for learning your way around building somewhat useful utilities in Clojure.

Now, we just need to package this application into a executable JAR. Doing that with Leiningen is also straightforward with the uberjar command. First of all, let’s mark which class will be main. Edit your project.clj to include that information:

(defproject cmd-app "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]]
  :aot [cmd_app.core]
  :main cmd_app.core)

Also, notice the “:aot [cmd_app.core]” line in the project.clj, it tells the Leiningen what namespaces to compile ahead of time.

Build a standalone JAR:

shelajev@shrimp ~/repo/tmp/cmd-app » lein uberjar
Compiling cmd_app.core
Compiling cmd_app.core
Created /Users/shelajev/repo/tmp/cmd-app/target/cmd-app-0.1.0-SNAPSHOT.jar
Created /Users/shelajev/repo/tmp/cmd-app/target/cmd-app-0.1.0-SNAPSHOT-standalone.jar

Now you have a runnable JAR file. It is a small application, but you can easily grow it further.

If you are not a fan of command line applications but still want a generic entry point into your application so you can only worry about the business logic, check out our look into the subject with The Adventurous Developer’s Guide to Clojure and start hacking your app with a http server around it.

Conclusion

In this post we looked at a really simple example of modeling your data structures in a functional style using Clojure. Then we created a sample project for the command line application so you can try Clojure and refresh your functional programming skills.

OOP is not the only available programming paradigm and often when solving problems you want to exercise the functional way of thinking. There are two main challenges that prevent you from diving into the beautiful world of functional programming: inexperience in designing your programs without the explicit help of objects and inability to kick off a small working project that you can gradually improve on.

Trying out different approaches to programming and even programming languages you are not fluent in is a slow, not very rewarding process. I don’t doubt that at least once or twice a year you think about switching to Haskell, Erlang or something esoteric. However, my own experience shows that it is not that easy to do; however, if you start with small projects that are actually useful, then the skill will accumulate over time.

Hopefully, next time you need to write a small command line utility, you’ll remember this post and unleash the power of Clojure and functional programming onto the task. By the way, when you do it, please mention it to me @shelajev. I’d love to hear that.


Read more about Clojure and 7 other JVM languages on RebelLabs. There’s a great report that’s just dying to have you download it!

GET THE REPORT