swap! 문서에는 함수가 여러 번 호출될 수 있으니 부수 효과가 없어야 한다고 적혀 있다. 그런데 실제 코드에는 그 안에서 로그를 찍는 경우가 여전히 있다.
(def hits (atom 0))
(defn record! [id]
(swap! hits (fn [n]
(println "counting" id)
(inc n))))
아톰의 값은 어떤 경우에도 맞다. 커밋되는 시도는 하나뿐이기 때문이다. println은 그 커밋에 속하지 않는다. 두 스레드가 경쟁하면 진 쪽 시도는 이미 출력을 한 뒤에 다시 실행되고, 그래서 한 번의 호출에 줄이 두 번 찍힐 수 있다. dosync 안의 부수 효과와 같은 모양이고, 조정하는 장치가 없으니 오히려 더 쉽게 걸린다. 내가 쓰는 해법은 swap-vals!다. 이전 값과 새 값을 돌려주니 반환된 뒤에 로그를 남기면 된다.