DEV Community

Cover image for Learning Clojure, part III
Камило Куньа
Камило Куньа

Posted on • Updated on

Learning Clojure, part III

We already discussed the reasons you should try Clojure and also configured our development tools and installed Clojure.

Hello, Clojure!

As every developer knows since the dawn of computing the first program that we have to write to be successful in any programming language we're learning is print 'Hello World' on console.

For this we gonna start a new project:

$ lein new app hello-world
Enter fullscreen mode Exit fullscreen mode

And open it on our IDE:

$ code hello-world
Enter fullscreen mode Exit fullscreen mode

The project will have the following structure:

.
├── CHANGELOG.md
├── doc
│   └── intro.md
├── LICENSE
├── project.clj
├── README.md
├── resources
├── src
│   └── hello_world
├── target
│   └── default+test
└── test
    └── hello_world
Enter fullscreen mode Exit fullscreen mode

Where:

  • CHANGELOG: That's a model for CHANGELOG in the project.
  • doc: Is a folder dedicated to the documentation of the project, it's initialized with an intro.md for writing the first steps.
  • LICENSE: Is a file containing the Eclipse Public License - v 2.0 the same license used in Clojure and default in most Open Source projects that use the language.
  • project.clj: That we're gonna declare our dependencies and configuration for the project.
  • README: That's a entry document and front page in remote repository for the project.
  • resources: Where we can put the files we want to zip in the final jar when we compile the project.
  • src: That's where our code will really be.
  • target: Where will be the compiled jar's.
  • test: That's where the tests will be place.

Now we can run our code using leiningen:

$ lein run
Enter fullscreen mode Exit fullscreen mode

And if we want to build it as a jar (if you're not from Java and not familiar with the concept we'll explain next) for distribute we can use:

$ lein uberjar
Enter fullscreen mode Exit fullscreen mode

If we want to run the generated jar file:

$ java -jar target/uberjar/hello-world-0.1.0-SNAPSHOT-standalone.jar
Enter fullscreen mode Exit fullscreen mode

And we should receive the same message as before.

What's a jar?

The JAR (Java Archive) it's a compressed format of a compiled project for Java Virtual Machine (JVM). When the project is compiled to a JAR File all the JVM bytecode generated will be compressed in this file together with metadata and additional resources needed to run the code.

This is analog to what most people think about an auto executable .exe or .dll on Windows. The JAR file is the format that is used to distribute programs written to be executed in JVM or libraries to be used in languages that run on it.

How Clojure works

Clojure is 100% written in Java (and Clojure itself). In fact, the whole language runs from a JAR file that can be built from Clojure source code. But the process of compilation and execution of the code it's little different from Java.

When we run a Java program the source code is send to the compiler who will parse, tokenize, structure... the code and then compile it to a .class file that contains the compiled bytecode and that file when run will be sent to JVM who will translate it to the optimized machine code for where it's running.

Diagram of the code evaluation where shows that the characters of a file are sent to the compiler who's produces bytecode and then send to JVM execute

"Traditional Evaluation (Java)" by Rich Hickey is copyrighted material of clojure.org

By other way, when a Clojure program is evaluated first it passes by a special step that's the reader a program written for receive the source parse it and return all code structured in some data structure, only after it the code gets in compiler. In Clojure the compile only receive data structures and never text, separating the reader from compiling makes it easier to process macros and substitutions. As most times the Clojure program is running in live mode (like REPL) the bytecode is immediately sent to JVM that caches and executes it.

Diagram of the code evaluation where shows that the character of a file are sent to a reader who transforms it into data structures that are sent to compiler that generate bytecodes who are immediately send to JVM execute

"Clojure Evaluation" by Rich Hickey is copyrighted material of clojure.org

How our hello-world JAR works

If we use an online Java decompiler tool to analyze the compressed bytecode in the JAR we created when compile our project we'll get that the JAR has a folder structure like that:

hello-world-0.1.0-SNAPSHOT-standalone.jar
├── clojure
└── hello-world
Enter fullscreen mode Exit fullscreen mode

Where the clojure folder contains the compiled bytecode of the reader and compiler altogether with the language source compiled.

While the hello-world folder have the original Clojure file we written and also helper classes to run main and these same files compiled in Java, but the compiled result are internal symbols of the Clojure language and not a simple and readable Java program.

So every time we compile our Clojure apps for a JAR to be run in JVM the JAR itself contains also the whole code needed to run Clojure including the the language functions, reader and compiler that can be executed if needed.

See ya!

Our Clojure journey is still far from the end, now we can understand how the process compilation and execution of Clojure works we can understand how it's different from a Java project and how JVM can execute the JAR since it was not thought to run Clojure code. Hope to see you in part IV.

Top comments (5)

Collapse
 
strafer14 profile image
Michael Ostrovsky

Thanks! I've been curious about clojure & cjs for a couple of years now and did a side-project myself and absoultely loved it.

I think the dream of it being a business-viable language is still far, even though I have seen a few companies use it for their backend.

Collapse
 
cazevedo profile image
Камило Куньа

Where I work we're using to build all our applications from frontend with ClojureScript and React (reagent) to the backend (compojure) and I absolutely love it too, I would even say that is probably one of most pragmatic functional programming language to choose for build products (maybe behind Elixir).

The main problem in being a more viable option is the fact that Clojure is not popular as Java or Ruby, is hard to find developers that are willing to learn a language that is so different and not so popular, so when starting a new thing in Clojure is very hard to scale the team for scale the product.

One of my main goals in dev.to is to make more people have interest in experiment Clojure, I think even most people don't use it as daily basis there's a lot of benefit in experiment different ideas in programming and hope that more people goes further than the initial antipathy on parenthesis and try it.

Collapse
 
strafer14 profile image
Michael Ostrovsky

Awesome! Thanks for your reply, I think clojure is beautiful and has contributed a lot to my current coding skills (I'm a web developer mainly using node and react) and so even if people will not use it in their day to day a side project can still bring a lot of value in thinking about problems from a different angle than they're used to.
Another tool for the arsenal!

Collapse
 
puredanger profile image
Alex Miller

The diagrams were copied without attribution from clojure.org/guides/learn/syntax. Could you at least add attribution? Images on the clojure.org web site are copyright Rich Hickey.

Collapse
 
cazevedo profile image
Камило Куньа

Sure, I thought whole clojure.org was on EPL 2.0, but as the footer says only the website code is. As the content is copyrighted I will add the attribution.