Getting Started with Clojure

in #programming7 years ago

Hey fellow steemit community! I wanted to share the love and joy that is the Clojure programming language.

Now if you aren't familiar with Clojure, here is the description from https://clojure.org/

Clojure is a dynamic, general-purpose programming language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming. 

There is a lot going on in this sentence, but that's because Clojure has a lot going on under the hood. Lets break it down:

  • Dynamic: It doesn't use Types (at least not at compile time).
  • General purpose: this is opposed to a domain specific language like SQL or HTML. It also has the property of being Turing Complete. Which means that you can implement a [Turing Machine](https://en.wikipedia.org/wiki/Turing_machine) with the features of Clojure.
  • Interactive Development: The almighty REPL, I'll get into more detail on this later.
  • Multithreaded programming: Clojure's core library is very conducive for multithreaded or parallel programming  because it is a functional language.

There is another key detail about Clojure that is discussed further down in the description:

Clojure is a dialect of Lisp, and shares with Lisp the code-as-data philosophy and a powerful macro system. 

If there is anything you should learn from this post, it is that Lisp is awesome!!!

According to Wikipedia, Lisp is the oldest high level programming language next to Fortran. Programming history is neat! So why use it now? Because Lisp has very little syntax, almost no syntax. It uses parentheses and prefix notation to denote expressions of code (technical term being S-Expressions, which stands for Symbolic Expressions). And that is it!

Let me demonstrate with a quick example of addition:

In a language like Java you can perform addition like this:

int n = 1 + 1;

But in Clojure it would be like this:

(def n (+ 1 1))

If you are new to Lisp, you are probably wondering why that was a good idea. You have to remember that Lisp was originally conceived of to be written on punch cards. Using s-expressions meant you could express functions just like data. This meant there was very little syntax, thus being simpler to use.

Now why is Clojure a dialect of Lisp, well because Clojure uses s-expressions to denote code like Lisp does and it also has the ability to use macro's. And it steals a couple of other ideas as well. There were many other dialects of Lisp like Scheme, Racket, or Common Lisp. Clojure goes beyond the original Lisp by introducing the "[]" and "{}" brackets. I will show what you use them for in a second.

The reason Clojure has become one of the more successful languages in the Lisp family is that it is hosted on the JVM (Java Virtual Machine). I've once heard that the JVM is one of the most advanced pieces of technology ever created by mankind. It may be slow to startup but it sure is a powerhouse at runtime and it handles multithreading extremely well. An interesting tidbit is that Clojure is also hosted by Javascript as well with the Clojurescript project. I will only focus on Clojure for this post though.

So why not just write Java if the JVM is so great? Well, the create of Clojure, Rich Hickey had been doing just that for decades and decided that he needed something better. Java is not known for having very elegant syntax, which is where the Lisp part comes in. The other thing is that Java is an Object Oriented Programming language. Rich Hickey argues OOP creates unnecessary complexity when writing code. He makes a good point by posing this question:

How do start solving a problem in Java? You make a class.

Basically, this is like the old saying, everything looks like a nail when you have a hammer in your hand. Java is great, but Rich Hickey felt that we as programmers could do better. Rich Hickey wanted to write concurrent and parallel software but found that Java's OOP style and heavy use of mutable state did not lend itself well to this. That is why functional programming is becoming so much more popular. Parallel programming is a must now that we are running into the limits of Moore's law, we have to use more cores. And functional programming is very well suited for this. The main reason being that it uses immutable state by default. What does that mean? If you are on steem then you probably know about blockchain? And you know how blockchain keeps things forever? We could say the blockchain is immutable. Now Clojure programs don't run on a blockchain, so the value doesn't persist forever, just for the duration of the program. The reason immutable state is useful when doing parallel programming is that you don't run into race conditions. Which is when to thread's on your machine try to change a certain value at the same exact time. What is the expected value? Indeterminate. When trying to write complex multithreaded code this is the last thing you want to deal with.

So now that I have discussed why you should program in Clojure, I am going to show you how to get started like the title of this post promised!

First off make sure you have java installed!

Then you can install my preferred Clojure build tool boot. Follow the appropriate instructions on the README to install it on your machine. Now there is another clojure build tool called Leiningen, however I prefer boot because it is more flexible and gives greater control over the build process.

Once you have boot installed we can get started quickly with a project template I've made which also includes an IDE as a dependency, cool right?!

boot -d boot/new new -t boot-nightlight-template -n clojure-newbie

 This creates a directory called clojure-newbie with all the the appropriate files we need to get started. After running the above command you should have a directory that looks like this:

clojure-newbie
├── LICENSE
├── README.MD
├── build.boot
└── src
    └── clojure_newbie
        └── core.clj

Now cd into the clojure-newbie directory and run "boot night" in your terminal. This starts up the nightlight editor, which we can then access in our browser at "http://localhost:4000". We can now navigate our project directory in our browser. nightlight is currently my preferred IDE for clojure, there are other ones like Emacs, Cursive, and Proto-Repl that are also great. I like nightlight because you can get started with a lot of hassle and it has rainbow parentheses!!! :D

The first file to notice is the build.boot file that looks like this:

(set-env!
  :resource-paths #{"src"}
  :dependencies '[[org.clojure/clojure "1.9.0-alpha15"]
                  [nightlight "1.6.5" :scope "test"]]) (require   '[nightlight.boot :refer [nightlight]]   'clojure-newbie.core) (deftask night []   (comp     (wait)     (nightlight :port 4000))) (deftask run []   (with-pass-thru _     (clojure-newbie.core/-main)))

At the top is our environment setup where we list our dependencies, when we want to use other Clojure/Java libraries we will list them there, and boot will automatically fetch them for us. The other thing to notice our two tasks, night and run. night is the boot task we used to startup nightlight (isn't boot cool?!). The other task will run the code in our core.clj file. We will be using the REPL for the duration of this post, so we won't need this task for now.

Now in nightlight navigate to the Clojure REPL. REPL stands for READ - EVAL - PRINT - LOOP. It is basically an interactive shell to try out different Clojure commands or to run scripts. Clojure folks love it and make heavy use of it. Now in our REPL lets start coding. Remember how Lisp has very minimal syntax? Yeah, so this won't take very long to show you the basics.

First, we will define some variables like we showed earlier:

(def n 5)

This defines the value 'n' as 5. Let's define another variable:

(def n2 6)

And we can use these two values to do some math:

(+ n n2)

This evaluates to 6. Remember Clojure is a Lisp so it uses prefix notation. Mathematical operators are just functions, they are not treated specially like other languages. You'll see why now, as we define our first function.

(defn add-2 [n] (+ n 2))

As the name suggests we defined a function called add-2 which does what it says it does. I will take the time to point out a few things here. We used the word defn as opposed to def to denote we are defining a function. The next values are the function name, the list of parameter names, and the function body.

Now to call this function we simply do this:

(add-2 5)

Which will return 7. 

Let's break this down. The way to do a function call is that within a pair of parentheses (s-expression) we first list the function name and then pass in the values to that function. But wait a minute? Didn't we do the same thing for def, defn, and +? Yes!!! Those are all functions as well! That is why math operators are prefix notation because they are treated just like functions.

Now lets go onto the part that Clojure really shines at. Working with data, and we will introduce some new language features. Lets define a vector with 4 numbers in it.

(def nums [1 2 3 4])

That was easy enough. Notice we used [] brackets this is to denote a vector. Remember Clojure uses immutable data so vectors in Clojure are persistent. The values of nums will always be [1 2 3 4]. The next data structure I will introduce is maps (think python dictionaries or hash-maps). We can create a map in clojure like this:

(def mappy {:foo "bar" :bar "foo"})

Defining maps in Clojure works in pairs, 1st value is the key and the second value is the value (lol), and so on. Feel free to mess around with these some more. But for now I am going to go back to working with vectors.

Remember that function we made earlier called add-2? Well we are going to use it to add all the values in nums by 2. We can use this with clojure's handy dandy map function. This is not to be confused with the data structure maps which we just discussed. I would say this is unfortunate naming, but there is a reason for it, and it goes all the way back to mathematics. The map function is extremely useful. I use it all the time! This is your go to iterator since we don't use for loops like Java.

(map add-2 nums)

This returns [3 4 5 6]. The arguments to the map function are the function to be applied, and the data structure to apply the function on.

We could also make an anonymous function to do the same thing:

(map (fn [n] (+ n 2)) nums)

Anonymous functions are very useful in all sorts of cases. In Clojure, functions are first class entities and they can be passed around as arguments. This is a feature of it being a functional programming language.

The other famous functional programming features are the functions filter and reduce. We can use these to do other types of operations on our nums data structure.

(filter even? nums)

This returns all of the even numbers in the nums vector.

Once again it is a similar pattern to the map function in that we pass in the name of a function, in this case even? which returns true if the number passed in is even, and a data structure, in this case a vector.

Now lets use reduce to add up all the numbers in nums:

(reduce + nums)

Which returns 10. Now that we have demonstrated some of the basic features of Clojure you can call yourself a functional programmer!!!

Hopefully you found this enlightening. I sure know that sometimes the hardest part with learning something new is just getting started. If this is your first time using a functional programming language, be patient. If you are experienced with other languages you will probably have to unlearn some stuff to wrap your head it. Clojure is a wonderful community and one of my favorite parts is listening to the all of the great talks on ClojureTV. Especially Rich Hickey's talks. He is known for his very deep and insightful philosophy about coding.

If you are interested in other Clojure projects (especially data analytics) you can follow some of my work on github.

Sort:  

Haha I love it thank you, you deserve so many followers!!!

Thanks for sharing... Love it.

Congratulations @hswick! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes received
Award for the number of comments

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Always meant to learn a lisp. Closure might be the one :)

Honestly, just learning it made me a better programmer when using other languages as well.

Coin Marketplace

STEEM 0.21
TRX 0.25
JST 0.038
BTC 95691.61
ETH 3343.89
USDT 1.00
SBD 3.03