Closures in Clojure
Clojure supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.
(ns closures-example
(:require [clojure.core :refer [println]]))
;; This function `int-seq` returns another function, which
;; we define anonymously in the body of `int-seq`. The
;; returned function closes over the atom `i` to form a closure.
(defn int-seq []
(let [i (atom 0)]
(fn []
(swap! i inc))))
(defn -main []
;; We call `int-seq`, assigning the result (a function)
;; to `next-int`. This function value captures its
;; own `i` value, which will be updated each time
;; we call `next-int`.
(let [next-int (int-seq)]
;; See the effect of the closure by calling `next-int`
;; a few times.
(println (next-int))
(println (next-int))
(println (next-int))
;; To confirm that the state is unique to that
;; particular function, create and test a new one.
(let [new-ints (int-seq)]
(println (new-ints)))))
To run this Clojure program:
$ clj -M closures.clj
1
2
3
1
In this Clojure version:
We define
int-seq
which returns an anonymous function. This function closes over an atomi
, forming a closure.The anonymous function uses
swap!
to increment the atom and return its new value.In the
-main
function, we demonstrate the use of the closure by calling it multiple times and showing how it maintains its own state.We also create a second closure to show that each instance maintains its own independent state.
The last feature of functions we’ll look at for now is recursion.