Getting Started with Clojure on Windows
Clojure is an amazingly powerful language. Using it (and watching Rich Hickey videos) has changed the way I think about programming, and the way I code in general. Once I learned the basics of the language, which was a relatively quick process, I fell in love and couldn't look back. I hope this post can help others who are new to Clojure get up and running quickly and painlessly.
This post is opinionated in the sense that I'll suggest certain tools to help those who are new to this scene get on their feet. The things you'll need are:
- Leiningen (pronounced LINE-ing-en) - This is like a package manager, build tool, task manager, and more in one tool. Think npm or nuget, but with more capabilities. There is at least one other build tool for Clojure (boot), but Leiningen is the most widely used.
- JDK - Clojure runs on Java. Throw out any qualms you may have about Java, we aren't coding in Java (though we can through Clojure, and sometimes that can be useful).
- IDE - I use Visual Studio Code as my editor, with the Calva extension for Clojure support, so this is what we'll use in this post.
We can actually install those first two in one go with Chocolatey, a package manager for Windows. I've installed these other ways before, and this way was the most frictionless.
Install Leiningen and the JDK
First, if you don't already have Chocolatey installed, follow the installation instructions at chocolatey.org. Once it's installed, open a Powershell or CMD terminal with admin priviledges and run the following:
choco install lein
You'll notice the Chocolatey package installs the OpenJDK and Leiningen. Let's start a REPL (read, eval, print loop).
Note: If you see a message that 'java' is not recognized as a command, close your terminal and reopen it, then try again.
You should see something beautiful like the following:
λ lein repl nREPL server started on port 52599 on host 127.0.0.1 - nrepl://127.0.0.1:52599 REPL-y 0.4.3, nREPL 0.6.0 Clojure 1.10.0 OpenJDK 64-Bit Server VM 12.0.2+10 Docs: (doc function-name-here) (find-doc "part-of-name-here") Source: (source function-name-here) Javadoc: (javadoc java-object-or-class-here) Exit: Control+D or (exit) or (quit) Results: Stored in vars *1, *2, *3, an exception in *e user=>
Clojure awaits you. Let's try simple addition:
user=> (+ 1 2 3) 6
Now we're in business! Hit
ctrl+D to exit the REPL. Let's get our editor set up.
Calva and VS Code
If you don't already have VS Code, go ahead and install it. Then let's create a project with lein. In your terminal, run:
lein new clojure-project
This will create a project in a new directory named
clojure-project. Let's open that directory in VS Code.
Now that we have this fresh new Clojure project, let's install Calva. In VS Code, go to Extensions and search "Calva" - install it. Now open the
core.clj file in the
src/clojure_project directory of your project, and hit the shortcut keys
ctrl+alt+c, ctrl+alt+j to run the Calva jack-in command, select
Leiningen as the project type when prompted. This starts a project REPL and connects Calva to it, and gives you a sweet REPL window in VS Code to work in. This is a souped-up version of what you saw in your terminal.
- Note: Before we continue, I want to point out a setting that I find very convenient in Calva that I suggest you turn on now, at least for the rest of this tutorial. Go into your VS Code Settings, then go to Extensions -> Calva and check the box next to "Eval On Save." This will ensure your code is compiled as you save your file, so you can immediately try it out in your REPL.
Notice at the top of your
core.clj file that you're in the
clojure-project.core namespace (
ns is the namespace function). All Clojure functions and vars live inside of namespaces, and usually code is organized as one namespace per file. The namespace your REPL started in is the
user namespace. Let's switch it to the
clojure-project.core namespace so we can run code from that namespace/file. Type the shortcut keys
ctrl+alt+c, ctrl+alt+n to switch the the current namespace (of the opened file).
You should see the prompt in your REPL window changed to
clojure-project.core=>, indicating that your REPL is now in that namespace. Calva was also nice enough to compile that namespace when we switched to it, so let's run that
foo function that was generated by Leiningen. In your REPL, type:
alt+enter. You can also just hit
enter if your cursor is at the end of the line. You should see that it printed the message from the function. Change the contents of the message, save the file, and run
foo again in your REPL. You should see the changes. Pretty fast development cycle, right? It makes working in Clojure a pretty fun experience.
Using Comment Forms for Testing
Another useful thing you can do is eval the current form (expression inside parentheses), or the top level form, which is another command, and have the result either printed inside your editor as an annotation or you can send the form to the REPL window to be evaluated. This is useful to quickly run a small bit of code from the editor as you're developing.
Something I sometimes do when testing code, is use Clojure's
comment function to create a comment block, then add all my test calls inside the comment block. This way the function calls won't occur on file save (if Eval On Save is turned on), and I can send them one by one to the REPL, or evaluate them in the editor. Then when I return later I have the sequence of calls saved in a file. It's not something I would leave in prod code, but it's useful for development.
(comment ;;;; These can be eval'd individually in the editor or in the REPL (foo "test") (println "hello Clojure") (+ 1 2 3) )
I encourage you to try out Calva's many different commands. Hit
ctrl+shift+p and type "calva" to see a list of all its commands.
If you're unfamiliar with Clojure as a language, I suggest you read Clojure for the Brave and True. It's free, it's the book I first read to learn Clojure, and I found it pretty good at teaching the basics and then building on those to explore more advanced concepts.
Clojure.org is another great resource for learning Clojure. The Guides section of the site has in-depth content on specific concepts.
The Clojurians Slack is a great place to get answers to those specific questions that might be hard to search. I've asked many questions in the beginner channel there, and usually someone answers within minutes.
A good way to get familiar with the language's vast array of functions is to do problems on 4clojure.com.
The best way to learn, at least for me, is to build something. Start a new project, or use the one we just created, and set a goal of something to build - maybe a simple web server, maybe a small game, maybe something useful that you need for work. You may not know the exact steps to get to the finished product, but the point is to figure them out as you go! And don't forget, the community is always there to help.