A guide to Clojure’s threading macros

Arrow macros are alternatively referred to as threading macros. Threading macros are a group of macros enabling us to pass a value through a sequence of expressions, enhancing code readability and expressiveness.

There are three threading macros in Clojure:

  • Thread-first macro

  • Thread-last macro

  • Thread-as macro

Thread-first macro

The thread-first macro is represented as -> in Clojure, and it threads a value through a series of steps, passing the result of each step as the first argument to the next one. This helps create a straightforward and readable chain of transformations on the value.

Syntax

(-> x & forms)

Parameters

  • x: This is the initial value to be threaded through the forms.

  • forms: This is a sequence of forms (expressions) where x is passed as the first argument to each form.

Coding example

The following is an example using the thread-first macro ->:

(def structure {:classes [{:grade :middle-school
:students [{:name "Olivia"
:gender :female
:age 8}
{:name "Ava"
:gender :male
:age 9}
{:name "Emma"
:gender :female
:age 8}
{:name "Jack"
:gender :female
:age 9}
{:name "Oliver"
:gender :male
:age 8}
{:name "James"
:gender :male
:age 9}]}]})
; Now, we want to get the first student name of the list of the class using threading
(println "First student of the list:"
(-> structure
:classes
first
:students
first
:name))
Explanation

In the example above, we want to access the first student’s name on the list using the thread-first macro ->.

  • Lines 1–19: We specify a list of students with their names, gender and age.

  • Lines 22-28: We use the thread-first macro -> to receive the collection as the first argument and return the first student’s name on the list.

Thread-last macro

The thread-last macro is represented by ->> in Clojure. It’s like ->, but it adds the value as the last argument in each step rather than the first. This is handy when using functions that expect the value as the final argument, such as conj or reduce.

Syntax

(->> x & forms)

Parameters

  • x: This is the initial value to be threaded through the forms.

  • forms: This is a sequence of forms (expressions) where x is passed as the last argument to each form.

Coding example

The following is an example using the thread-last macro ->>:

(def structure {:students [{:name "Olivia"
:gender :female
:age 8}
{:name "Ava"
:gender :male
:age 9}
{:name "Emma"
:gender :female
:age 8}
{:name "Jack"
:gender :female
:age 9}
{:name "Oliver"
:gender :male
:age 8}
{:name "James"
:gender :male
:age 9}]})
(println "List of male students:"
(->> structure
:students
(filter #(= :male (:gender %)))
(map :name)))
Explanation

In the example above, we want to access the male students and retrieve their names using thread-last macros.

  • Lines 1–18: We specify a list of students with their names, gender and age.

  • Lines 21-25: We use the thread-last macro ->> to receive the collection as the last argument and return a new collection that is the list of male students.

Thread-as macro

The thread-as macro is represented as as-> in Clojure, and is used when we want to give a specific name to the threaded value within the threading form. It allows us to explicitly name the intermediate result, making our code more readable.

Syntax

(as-> value name & forms)

Parameters

  • value: This is the value we want to thread through the forms.

  • name: This is a symbol to give a name to the threaded value within the scope of the forms.

  • forms: This is the forms (expressions) where we can use the named value.

Coding example

The following is an example using the thread-last macro as->:

(defn calculate-square [x]
(as-> x num
(* num num)))
(println "Square of 5 is:" (calculate-square 5))
Explanation

In this example,

  • Line 1: We define a function calculate-square that takes a number x.

  • Line 2: Inside the function, we use the as-> macro to give the name num to the input x.

  • Line 3: Then, we square the number and return the result.

  • Line 5: When we call (calculate-square 5), it calculates the square of 5 and prints the result, which is Square of 5 is: 25.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved