Not arguing that the following method can be trusted as much as in Haskell but properly used also prevents this kind of scenario:
https://clojuredocs.org/clojure.core/io℅21
The 'io!' macro marks a code block to have side effects which prevents using it in a STM transaction as 'dosync' might need to execute the functions multiple times in case of conflicts during the optimistic locking.
But there are many more side effects than changing variables. Clojure makes no guarantees that a given function is referentially transparent, nor does it promise that a given function doesn't write to stdout/stderr, read from stdin, change the file system, make a network connection, send missiles to foreign countries, etcetera.