Learning Clojure Part 2: Basic syntax

Pavel Polívka - Jan 5 '21 - - Dev Community

In this next part, I will go over basic Clojure syntax and operations. We will learn all the basics we need to be productive.

Expressions

Clojure has two kinds of structures. Literals and operations.

Literals are your everyday data structures like numbers, strings, vectors, etc...

1
"awesome string"
["vector" "of" "awesome" "strings"]
Enter fullscreen mode Exit fullscreen mode

Operations are your everyday bread and water. It's how you do everything in Clojure.
Operations take form of:

(operator operand1 operand2 operand3 ... operandN)
Enter fullscreen mode Exit fullscreen mode

The important note here is that Clojure uses whitespace to separate operands.

Example operations:

 (+ 40 2)
;=> 42

(- 50 8)
;=> 42

(str "Contact" " these " "strings")
;=> "Contact these strings"
Enter fullscreen mode Exit fullscreen mode

Flow

Clojure has some basic control flow operators, that will make our life easier. Let's go over the most basic ones.

if

With if you can do conditions in your code.

Structure of if expression:

(if boolean
 then
 else)
Enter fullscreen mode Exit fullscreen mode

So the basic example here would be something like this:

(if true
 "Clojure seems awesome."
 "Clojure seems like a lot.")
;=> "Clojure seems awesome."
Enter fullscreen mode Exit fullscreen mode

do

With do you can chain multiple expressions into one.

(if true
 (do (println "Clojure seems awesome.")
 (println "And more awesome with do."))
 "Clojure seems like a lot.")
;Clojure seems awesome.
;And more awesome with do.
Enter fullscreen mode Exit fullscreen mode

when

With when you have a combination of if and do. You do not have an else operand tho.

(when true
 (println "Clojure seems awesome.")
 (println "And more awesome with when."))
;Clojure seems awesome.
;And more awesome with when.
Enter fullscreen mode Exit fullscreen mode

booleans and nil

There are true and false boolean values in Clojure. nil represents the no value.

You can check if a value is nil with nil? expression.

(nil? 0)
;=> false

(nil? nil)
;=> true
Enter fullscreen mode Exit fullscreen mode

Both nil and false stand for logical falseness, all other values are considered true.

(if "random string" 
 "this random string is true")
;=> "this random string is true"

(if nil
 "nil is true"
 "nil is false")
;=> "nil is false"
Enter fullscreen mode Exit fullscreen mode

Equality operator is =

(= 1 1)
;=> true

(= 1 2)
;=> false
Enter fullscreen mode Exit fullscreen mode

Clojure also has and and or operators. Those act bit differently than in other languages.

or returns the first true value or the last value. Example:

(or false nil "this will be returned")
;=> "this will be returned"

(or (= 0 1) (= "a" "b"))
;=> false

(or nil)
;=> nil
Enter fullscreen mode Exit fullscreen mode

and returns the first falsey value, or the last truth value (if where are no false values)

(and "a" "b")
;=> "b"

(and "a" nil false)
;=> nil
Enter fullscreen mode Exit fullscreen mode

Naming stuff

We can use def to name values in Clojure.

(def shopping-list
 ["Vodka" "Apple jiuce" "Red Bull"])
shopping-list
;=> ["Vodka" "Apple juice" "Red Bull"]
Enter fullscreen mode Exit fullscreen mode

Defining variables like this may seem a bit strange and hell of confusing when you would do multiple assignments into one name. This is something that should be reconsidered and done differently.

Let's do a small exercise that would demonstrate how to write code the Clojure way.

Let's image a following piece of Java code.

level = "info";
message = "message";
if (level.equals("info")) {
 message = message + " (FYI)");
} else {
 message = message + " (OMG)";
}
Enter fullscreen mode Exit fullscreen mode

This is perfectly fine piece of code. My first instinct was do something like this:

(def level "info")
(def message "message")
(if (= level "info")
 (def message (str message " (FYI)"))
 (def message (str message " (OMG)")))
Enter fullscreen mode Exit fullscreen mode

If you think about it and know about the defn to define new operators. You can do something like this.

(defn error
 [message level]
 (str message
 (if (= level "info")
 " (FYI)"
 " (OMG)")))
(error "message" "info")
;=> "message (FYI)"
Enter fullscreen mode Exit fullscreen mode

You can follow me on Twitter to get more content like this.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .