Get up and running with Clojure
John Stevenson helps us take our first steps with the functional and dynamic JVM language, in this taster of his Developer.Press title
John Stevenson helps us take our first steps with the functional and dynamic JVM language, in this taster of his Developer.Press title
There are many reasons why I really enjoy Clojure as a software development language. The most important of these is simplicity. Simplicity shines through in the syntax of the language as well as the overall design approach to software.
Clojure encourages a modular approach to software, breaking down complexity to clearly define data structures and composable behaviour. If you think of small packets of behaviour working together to produce something much larger than itself; this is how Clojure libraries and applications are designed.
Constructing things with Clojure reminds me of the Unix design; each aspect of it does one thing really well allowing you to chain them all together easily. The nature of the language encourages developers to create Clojure libraries and applications with a highly modular approach, providing a great way to build complex systems simply.
Functional design is elegant
In Clojure, any function you call returns a value when evaluated, even if that value is null. This means that functions can be used as arguments to other functions, helping you to design some very elegant and modular solutions.
Functions calling functions give the developer a way of dealing with complexity in a simple way. This is achieved by breaking down behaviour into effortless components that work cleanly together. Functions and data structures are represented by the same syntax (homo-iconicity), this helps make your code simpler, more concise and it encourages developers to become productive quickly.
Clojure comes with a dynamic runtime environment called the REPL. This dynamic environment allows you to define and run code as you write it, making the language even easier to learn and experiment with.
Coupled with the dynamic type nature of Clojure language, this makes development really fly. You can quickly define and redefine your functions in the REPL and add them to your codebase if valuable. The REPL can load in your project code and help you discover ways to extend and improve your code quickly without going through a lengthy build cycle.
Leveraging the Java platform
Having a functional language on the Java Virtual Machine (JVM) get projects delivered quickly by using a huge amount of libraries developers are already familiar with.
Clojure does not need to be a huge language because it can use so many tried and tested libraries. This ranges from its own growing set of libraries to the thousands of existing Java, Groovy and JRuby libraries.
Because of the language design, it is often easier to use many Java libraries from Clojure. For example, when doing swing programming, it is simpler using the doto function in Clojure to chain method calls, avoiding lots of plumbing code.
After nearly two decades of compiler and runtime optimisation by some very smart people (including Martin Odersky of Scala and Java Collections fame), the JVM is a very fast environment. In terms of performance, Clojure is up there with a typical C/C++ application, with no noticeable performance difference for most classes of application.
Deploying Clojure is just as easy as deploying Java. Everything is compiled down to byte-code onto the JVM. You create jar or war files and drop them in to the environment just like any other Java bundles. If your environment is not set up for Clojure, then you can create an uberjar, a jar containing your Clojure application and the Clojure libraries themselves. As Clojure is quite small, the uberjars remain a manageable size.
First Steps in Clojure
Getting started with Clojure can be as simple as firing up your browser and pointing it to the Try Clojure website, as shown in Figure 1. This website gives you a dynamic runtime environment where you can start writing Clojure straight away. Any code entered is evaluated immediately, giving you instant results from your code. This gives us a very rapid way of learning the language syntax.
Figure 1: tryclj.com repl in a web page
But wait, we don’t know any Clojure! We will cover the syntax of the language soon, but if you want a taster you can follow the simple tutorial on tryclj.com. All you have to do it to type tutorial in the tryclj.com window and follow the instructions. [Editor’s Note – soon means in the Developer.Press title]
As tryclj.com is a project on Github, you can get a copy and run the website locally. The project is written using a Clojure framework called Noir (which in turn uses other Clojure frameworks called Ring, Compojure and Hiccup). It gives you an example of a Clojure web project, which can guide you as you create your own web apps.
Your own Clojure development environment
TryClj.org is a great learning tool where you can experiment with the syntax of the Clojure language. To write your own applications though, you will want to set up a Clojure development environment on your own machine. Arguably the easiest and most humane way to work with Clojure is to use a tool called Leiningen (pronounced Line – ing – en).
Leiningen is a build tool designed especially for Clojure, allowing you to define your project tasks in Clojure. Absolutely no more files full of XML anywhere! Leiningen also manages all your project dependencies, just like Maven and Ivy. Leiningen is also used to deploy your Clojure project in a live environment, creating standard Java jar files. If the environment does not have Clojure already available, Leiningen can create an UberJar containing your application and Clojure.
Download the latest install script for Leiningen, called lein, from the website.
The lein install script will download a number of jar files that make up the Leiningen project. First add the lein install script to the execution path of your operating system and then run it to download the latest version.
Assuming the lein script is in your Downloads folder, move the lein script into a folder called bin in your home directory (create the bin folder if necessary):
mv ~/Downloads/lein ~/bin
Make the lein script executable:
chmod +X ~/bin/lein
If this is the first time you have created a bin directory for the login account you are using, the environment settings need to be reloaded. Either logout and login again or type the command:
Run the lein script when you are connected to the Internet so it can download the required files lein.
Running Leiningen once installed
The same script to install Leiningen also runs it. When you run the lein script with no arguments it shows you a list of tasks you can perform.
Build jar and deploy to remote repository
|deps||Show details about dependencies|
|help||Display a list of tasks or help for
a given task
Install current project to the local repository
|jar||Package up all the project’s files into a jar file|
|new||Generate project scaffolding based on a template|
|pom||Write a pom.xml file to disk for Maven interoperability|
Start a repl session either with the current project or standalone
|run||Run the project’s -main function.|
|test||Run the project’s tests.|
|trampoline||Run a task without nesting the project’s JVM inside Leiningen’s|
|uberjar||Package up the project files and all dependencies into a jar file|
Upgrade Leiningen to specified version or latest stable
|version||Print version for Leiningen and the current JVM|
|with-profile||Apply the given task with the profile(s) specified|
Now you have Leiningen installed, you can use it to create your own Clojure projects. You can also use Leiningen to run the REPL to give you the dynamic coding environment. Next we will cover Clojure development with Leiningen.
REPL driven development with Leiningen
The REPL is a full Clojure environment where you can write code and get instant feedback on what it does. There is no need to fire off a separate compiler or run a build tool and there is no need to wait. Any correct Clojure code you write will run in the REPL.
Using the REPL gives you an opportunity to experiment and test out your assumptions quickly. Developers continue to use the REPL as part of their developer process as it’s a highly productive environment.
Once you have Leiningen installed, you can run the REPL using: lein repl as shown in Figure 2.
Figure 2: Starting up the REPL from Leiningen
When the REPL starts, it loads several Clojure libraries, so you can already use the core of the Clojure language. The REPL also loads in the basic Java libraries so you can use some familiar objects and API calls.
Once you have the REPL up and running you can call existing functions in the Clojure language as well as define your own. You can also define your own data structures that functions will act upon.
Everything in the REPL is kept in memory until you end your REPL session by calling the Clojure function exit: (exit)
Writing Clojure code in the REPL
You can type Clojure code directly into the REPL and it will be evaluated once you create a complete expression. An expression is a piece of Clojure code defined within a balanced set of parentheses – round brackets. A really simple example is shown in Figure 3:
Figure 3: Simple adding in Clojure
Here we are using the + function to add up several numbers and when we press return the expression is evaluated. The result of the function is displayed on the line following the code we have entered. We are then prompted to enter more Clojure code.
Getting work done by calling functions
In Clojure you get the impression that everything is a function, even data structures act like functions. This is a great thing about the language, but can be a source of confusion at first. As we have seen in the previous example, calling a function is simply a matter of putting it in between parenthesis as the first item. Here are some more examples to try. A familiar way to print strings is to use the println command. When used in the REPL, println will output in the REPL window, as shown in Figure 4.
Figure 4: Printing to standard out
Notice that after the string is printed, the value nil is returned. All functions return a value when evaluated. If no value is generated by the function, then a nil value is returned by default. The list function generates an ordered list of numbers from the arguments given, like in Figure 5.
Figure 5: A sample list data structure
Functions can be part of the arguments to another function (and arguments to themselves as well). In the next code example (Figure 6), we first create a list which is ordered but is not arranged in numeric order. By wrapping the list function in a sort function, the value returned from list is sorted before being returned.
Figure 6: Examples of using the list function
There are many functions that work on lists and other collections of data. For example, you can use the function max to find the largest numerical value from a list of numbers, as shown in Figure 7.
Figure 7: Finding the maximum value
You also have functions that explicitly use other functions to process a collection of data, for example map and apply.
map will take the function it has been given and run it with each of the elements in a collection (in this case an array, see Figure 8). So each number in the array has the inc function mapped to it, incrementing each number in turn before returning the result.
Figure 8: Using the map function
Show me the documentation
If you want to understand what a function does, you can either search for it on clojuredocs.org, or look at the built-in documentation as shown in Figure 9.
Using the doc function you can read the documentation for any function you specify as an argument, even (doc doc).
Figure 9: In-built documentation for the map function
As you are still discovering the wide range of functions in Clojure, you probably don’t know the name of all of them. Using the function find-doc (Figure 10) you can search through all the functions available from the REPL. This is also handy if you are programming on the move and don’t have an Internet connection.
Figure 10: Documentation for the find-doc function
So if we want to use a function that iterates over a data structure, we can use find-doc to list those functions that may help us (see Figure 11). The find-doc function returns the descriptions of three functions that relate to the concept of iterate.
Figure 11: Finding the in-built documentation for functions that iterate
Missing some functions
If the function doc does not work, then it could be that the library it is held in a Clojure namespace and has not been added to your environment. To use the doc function and several other useful functions, add the library clojure.repl to your namespace with the function use (use ‘clojure.repl)
Show me the source code
To get inspiration as you are learning Clojure and to see common coding approaches, including documentation styles, you can use the source function to look at the Clojure code for any function the environment knows about, like in Figure 12.
Figure 12: Viewing the source code for a function
In this example, the function documentation also includes a map that defines when the documentation was added to the Clojure language. You can also go to the Clojure Docs website for access to definitions and source code
Author Bio: John is a Community Developer at Heroku & Salesforce and an active organiser of several communities in London. He runs workshops and speaks on technical topics including open source projects, developer tools, continuous delivery, TDD & BDD practices and declarative (functional) programming (Clojure). John also presents on kanban as a way to help individuals, teams and organisations become more effective. He is a strong advocate of group learning and encourages others to get involved with the community for their own personal growth. In his spare time, John likes to cycle quite a lot (200-400km) on a weekend if he is not too busy learning.
This is an excerpt from John’s Developer.Press title ‘Clojure Made Simple‘, priced at $3.99. Developer.Press offers digital format books on Java, PHP, mobile technologies and more at low prices – find out more at the Developer.Press website and check out the new releases.