Ankur's answer is not thread safe, although I don't think the description of this is very useful, and its alternatives are worse. It’s reasonable to say, “Well, I’m not worried about multiple threads now,” in which case this answer is fine. But it’s important to be able to write such things safely, even if you don’t need this guarantee in any particular instance, and the only safe way is to make all your logic inside swap! , eg:
(let [m (atom {})] (defn get-index [token] (get (swap! m #(assoc % token (or (% token) (count %)))) token)))
You can speed it up a bit by avoiding swap! if there is already a record when calling the function, and avoiding communication if there is already a record after you entered swap! , but you should "double check" that there is no record on the card for the current token before just assigning it (count %) , because some other thread could get in before the start of swap! ing (but after you decided to swap! ) and the value for the current token is assigned, in which case you should respect this assignment instead of creating a new one.
Edit: as an aside, the Java version, of course, has the same problem in terms of thread safety, because by default everything in Java is mutable and is not thread safe. At least in Clojure you have to put there ! : "Yes, I know it’s dangerous, I know what I’m doing."
So, in a way, Ankur's solution is a perfect translation of Java code, but it would be even better to improve it!
amalloy
source share