Explore how to evaluate expressions in the Clojure REPL, including arithmetic operations, function definitions, and data structure manipulations, tailored for Java developers transitioning to Clojure.
Welcome to the world of Clojure, where the REPL (Read-Eval-Print Loop) is your interactive playground. As experienced Java developers, you’re accustomed to compiling and running your code to see results. In Clojure, the REPL allows you to evaluate expressions on the fly, making it a powerful tool for experimentation and learning. In this section, we’ll explore how to evaluate various types of expressions in the REPL, including simple arithmetic, function definitions, and data structure manipulations.
Before diving into evaluating expressions, let’s briefly understand what the REPL is and why it’s essential in Clojure development. The REPL is an interactive environment where you can enter Clojure expressions, evaluate them, and see the results immediately. This immediate feedback loop is invaluable for testing ideas, debugging, and learning the language.
Let’s start with something familiar: arithmetic operations. In Clojure, arithmetic expressions are written in prefix notation, which might be different from what you’re used to in Java. Here’s a simple example:
;; Adding two numbers
(+ 3 5) ; => 8
;; Subtracting two numbers
(- 10 4) ; => 6
;; Multiplying two numbers
(* 6 7) ; => 42
;; Dividing two numbers
(/ 20 4) ; => 5
In Clojure, the operator comes first, followed by the operands. This prefix notation is consistent across all operations, making it easy to remember and use.
Open your REPL and try evaluating these expressions. Experiment by changing the numbers and operators to see how the results change.
Functions are first-class citizens in Clojure, meaning you can define, pass, and return them just like any other data type. Let’s define a simple function in the REPL:
;; Defining a function to add two numbers
(defn add [a b]
(+ a b))
;; Calling the function
(add 3 5) ; => 8
In this example, we define a function add
that takes two parameters, a
and b
, and returns their sum. The defn
keyword is used to define functions in Clojure.
In Java, defining a similar function would look like this:
public int add(int a, int b) {
return a + b;
}
Notice how Clojure’s syntax is more concise and expressive, focusing on the operation rather than the boilerplate code.
Define your own functions in the REPL. Try creating a function that multiplies two numbers or calculates the factorial of a number.
Clojure provides a rich set of immutable data structures, including lists, vectors, maps, and sets. Let’s explore how to manipulate these data structures in the REPL.
Lists are ordered collections of elements. Here’s how you can create and manipulate lists in Clojure:
;; Creating a list
(def my-list '(1 2 3 4 5))
;; Accessing the first element
(first my-list) ; => 1
;; Accessing the rest of the list
(rest my-list) ; => (2 3 4 5)
;; Adding an element to the front
(cons 0 my-list) ; => (0 1 2 3 4 5)
Vectors are similar to lists but provide efficient random access. Here’s how you can work with vectors:
;; Creating a vector
(def my-vector [1 2 3 4 5])
;; Accessing an element by index
(nth my-vector 2) ; => 3
;; Adding an element to the end
(conj my-vector 6) ; => [1 2 3 4 5 6]
Maps are collections of key-value pairs. Here’s how you can create and manipulate maps:
;; Creating a map
(def my-map {:a 1 :b 2 :c 3})
;; Accessing a value by key
(get my-map :b) ; => 2
;; Adding a new key-value pair
(assoc my-map :d 4) ; => {:a 1, :b 2, :c 3, :d 4}
Sets are collections of unique elements. Here’s how you can work with sets:
;; Creating a set
(def my-set #{1 2 3 4 5})
;; Checking if an element is in the set
(contains? my-set 3) ; => true
;; Adding an element to the set
(conj my-set 6) ; => #{1 2 3 4 5 6}
Experiment with these data structures in the REPL. Try adding, removing, and accessing elements to see how they behave.
In Java, collections such as List
, Map
, and Set
are mutable by default. Clojure’s immutable data structures provide several advantages, including thread safety and easier reasoning about code. Here’s a comparison of creating a list in Java and Clojure:
// Java List
List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);
;; Clojure List
(def my-list '(1 2 3 4 5))
Notice how Clojure’s syntax is more concise and expressive, focusing on the operation rather than the boilerplate code.
reduce
function.For more information on Clojure’s data structures and functions, check out the Official Clojure Documentation and ClojureDocs.