Simulate local variables in Clojure with Atoms

Reading time ~2 minutes

I write Java for a living. I’m familiar with classes having state. For example:

public class EchoService {
    private Map<String, String> messages = new HashMap<>();

    public String getMessageForKey(String key) {
        return message.get(key);
    }

    public void setMessageForKey(String key, String message) {
        messages.put(key, message);
    }
}

How can I achieve something similar in Clojure? Perhaps defining a map (def messages {})? No, that won’t work because a def is immutable so I can’t add any elements to it. The good new is that I can use an atom.

What’s an Atom?

An Atom is a reference to something. That something can be any type of value, in this it refers to a map.

(def messages (atom {}))

deref

You can ask at atom to give you the value it refers to using deref

(deref ref)
(deref ref timeout-ms timeout-val)

Example

(deref messages)

swap!

Most importantly, for the purposes of this exercise, by using swap! I can apply a function to the value it refers to then have it refer to the result of that function.

(swap! atom f)
(swap! atom f x)
(swap! atom f x y)
(swap! atom f x y & args)

Example

(swap! messages assoc "key" "val")

The atom messages now refers to the map {"key" "val"}.

Putting it all together

Writing the equivalent of that Java code in Clojure

(def messages (atom {}))

(defn get-message-for-key [key]
    (key (deref messages))
)

(defn set-message-for-key [key val]
    (swap! messages assoc key val)
)

Book Review: Soft Skills: The software developer's life manual by John Sonmez

Rating: 9/10The title of "Soft Skills" suggested to me that this book might be about all the non-technical skills you need to get along a...… Continue reading

There ain't no T in TDD

Published on March 18, 2016