Part 3 — A complete beginner’s guide to Computer Programming with Clojure: Introducing LEIN and REPL.
Lein is an abbreviation of Leiningen and has its own website https://leiningen.org/. Lein, or more appropriately lein is the command used to create a new template for a specific programming project. In other words, lein will create lots of boilerplate code to save you much programming.
For example, we could have a project called First Project. We may want to put this project in a Directory called Project like so:
mkdir Projectcd Projectpwd
Open up a terminal. Use the terminal app or use the keyboard shortcut Ctrl + T. Typing the command mkdir Project creates the Directory called Project. The command mkdir means ‘make directory.’ The next command cd Project just takes you into the Project directory. The command cd means ‘change directory.’ At the end, the command pwd shows you exactly where you are in the directory tree. The pwd stands for ‘print working directory’ and is a useful command to remember as it allows you to instantly identify your location.
Let's use lein to create a new project called First Project.
lein new app first_project
Note, first_project is all lowercase. This is on purpose as lein will not allow you to use uppercase when creating a new project. If you try and use uppercase letters you will get an error.
Not much will happen except for the following lein-generated statement:
Generating a project called first_project based on the ‘app’ template.
All that will be created is a new directory. Type ls to see this new directory.
Next, change into the new directory by using the cd command.
Remember the pwd command should you wish to check the directory location.
Now we are inside the first_project directory we can look at the structure. Recall, I stated that lein creates lots of boilerplate code. Boilerplate code is code and structure that has already been created. This is all the general stuff that is commonly created; will save you much programming time by not writing this code each time you start a new project.
We can look at the contents of the directory in several ways. For instance, we can use our ls command or even ls -l to provide more detail. However, we will use the tree command.
Type tree to see the following:
For you, the most important files are core.clj and project.clj. core.clj is where you will write your primary code. The other file, project.clj is where you will call up dependencies. Dependencies are useful libraries of pre-written code used for specific functions. For example, there are various dependencies, or code libraries, concerning TIME and how to work and display time in its various formats. In short, these code libraries or dependencies help you by providing specific code for you to use in your projects. Again, saving you a lot of typing and pontificating.
We will eventually look closer at these files. For now, just familiarise yourself with the contents.
To see the contents of core.clj type:
… and for project.clj type:
You should see something like so:
Note the cat command. The is actually short for ‘concatenate,’ as in concatenate a bunch of files into one. However, cat is more often used to see the contents of a file. Also, note the use of the forward-slash /. This denotes a directory. As clore.clj is in a directory called first_project, which is under another directory called src, we cannot just type cat core.clj. We could have used the cd command to go into each directory one at a time. Instead, we chose to supply the directory names and separate each with the forward-slash /. Hence, cat src/first_project/core.clj
We touched on the REPL in the Introduction (Part 1). The following is a more precise definition of REPL:
- Read User input.
2. Evaluate the code.
3. Print any results.
4. Loop back to step 1.
Unless it’s already open, start up a terminal. Use the terminal app or use the keyboard shortcut Ctrl + T
To actually use the REPL we will invoke the command lein repl; after a short time, you will see the user prompt =>.
To print the string “Hello World”, type
(println “Hello World”)Hello World
To explain what just occurred, (println “Hello World”) is our input. The computer Read this input as soon as we hit the return key. Behind the scenes, it Evaluated the code. After evaluation, it Printed the results, Hello World and nil. Finally, it Looped back to the User prompt =>.
We actually see two results, “Hello World” and nil. Even though the REPL used the function println, it didn’t actually evaluate anything. All functions produce something even if it’s nil. This is confusing because we see two results. However, the result of the evaluation is nil as nothing was actually evaluated. The function println only printed its argument. Recall from Part 1, Clojure uses S-expressions consisting of a function followed by a number of arguments. In our case, there was only one argument. In short, the function must do some sort of evaluation to actually produce something other than nil.
Look at these examples:
(+ 5 10)=> 15 (+ 5)=> 5(+ 5 0)=> 5(println 5)5
As already stated, a function like println is said to evaluate to itself. In other words, it doesn’t return anything new. Hence, it returns nil.
It’s tempting to just copy and paste the code from these posts into the REPL. However, you may get errors as certain characters such as speech marks “” and carrots ^ etc. may not be exactly the same. There are different ASCII version of characters and some will not be interpreted correctly. So, always manually type the examples. But if you forget and see an error, consider whether you pasted or typed the example? All the examples have been tested.
In Part 1, we talked about the JVM and the Java programming language. We have also talked about libraries, i.e. pre-written code. Clojure also allows us to use Java to add additional functionality to our programs.
The code below imports the JFrame libraries from the javax.swing toolkit. Let me explain, javax.swing is known as a package (or toolkit) that contains components, or component parts, for creating a GUI (graphical user interface). From the javax.swing package we wish to import JFrame which is little more than a GUI window (For other components, check out this site: https://docs.oracle.com/javase/7/docs/api/javax/swing/package-summary.html).
To use the JFrame library type the following:
(import ‘(javax.swing JFrame))
The two examples below, both use the JFrame library to create a simple window. The second version adds the JLabel library to add the text, ‘Hello World Again!’ inside the window. To reiterate, the libraries JFrame and JLabel are pre-written code to produce specific component parts.
(let [f (JFrame. “Hello World”)] (doto f (.setSize 400 200) (.setVisible true)))
This time we will import JLabel as well:
(import ‘(javax.swing JFrame JLabel))(let [f (JFrame. “Hello World”)label-text (JLabel. “ Hello World Again!”)](doto f(.add label-text)(.setSize 400 200)(.setVisible true)))
Type in both code listings above. At this stage, don’t worry if you don’t understand what you are typing. For now, recognize that the REPL knows an incomplete statement and creates a new line for you to continue typing. Hence, the #_=> symbol. Experiment with the .setSize numbers and change the text from “Hello World” to something else. Get comfortable with typing these simple programs until you can do it from memory.
Once you have finished with the REPL, type exit to quit and return to the Linux command line.
In this section, we introduced two of the most important and useful parts of Clojure: Namely, Lein and REPL. It should be clear that Leinigen is a powerful Clojure toolkit for creating a variety of projects with pre-written code and structure. Commonly used pre-written code is referred to as Boilerplate code. The REPL is a powerful tool for us to try and test our code as a whole or in chunks. The command lein repl starts our REPL session, and exit takes us out and back to the system prompt.
We also introduced a number of Linux commands. We can use mkdir to create a new directory and cd to change into a specific directory. To see where we are in the directory, we use pwd. In addition, we can access files in subdirectories with /. The commands cat and tree allow us to view file contents and directory structure respectfully. Else, we can see a directories content with ls and ls -l.
Finally, we did some coding within the REPL and took advantage of the javax.swing library to create components for a simple app. This also demonstrates the close link between Clojure and Java. However, due to the Abstract nature of Clojure, often less Clojure code is required to produce the same result.
By now, you should have enough experience of the REPL to move on to more advanced coding.