Once you learn Clojure (or any programming language) well enough to tackle a large project, you are going to run into lifecycle, dependency, and state management issues.
Two great resources for handling lifecycles, dependency, and state in Clojure apps are Mount and Component. I use Mount for my projects, but both are popular solutions. This post is about tolitius/Mount.
Simple Mount Example
The first step in using any Clojure library is to include it as a dependency in your project. I’m using lein, so the project.clj needs the Mount dependency.
1 2 3 4 |
:dependencies [ [org.clojure/clojure "1.10.1"] [mount "0.1.16"] ] |
You can find the latest dependency code by searching for ‘clojars’ on the Mount project page.
Next, we need some sample code. How about a stateful thread?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
(ns example.state-one (:require [mount.core :refer [defstate]])) (def should-run (atom true)) (def state-one (atom 0)) (defn- stateful-task-one [] (doto (Thread. (fn [] (loop [] (swap! state-one inc) (println "internal state is " @state-one) (Thread/sleep 1000) (if @should-run (recur))))) (.start)) state-one) (defn- stop-it [] (swap! should-run not) (Thread/sleep 2000) (println "Stateful task finished.")) (defstate my-stateful-thing :start (stateful-task-one) :stop (stop-it)) |
Now for a main method to use the stateful dependency.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
(ns example.core (:require [mount.core :as mount] [example.state-one :refer [my-stateful-thing]]) (:gen-class)) (defn -main "I don't do a whole lot ... yet." [& args] (mount/start) (println "Checking the current state" @my-stateful-thing) (Thread/sleep 3000) (println "One more check of the state" @my-stateful-thing) (mount/stop) (println "All done.")) |
Running this code should result in output similar to the following
1 2 3 4 5 6 7 8 9 |
internal state is Checking the current state 1 1 internal state is 2 internal state is 3 One more check of the state 3 Stateful task finished. All done. Process finished with exit code 0 |
This is a very basic example that should be easy to expand upon.