How does Clojure enforce that there are no side-effects in the transactional code? Is there a macro that "compiles" the transaction somehow?
STM in Haskell is very natural, since Haskell already enforces pure code and side-effecting code. STM and STVar work pretty similarly to IO and IORef or ST and TVar.
How does Clojure enforce that there are no side-effects in the transactional code?
Technically it doesn't. If you have a (println "foo") in a transaction it may be
printed multiple times if the transaction gets retried.
Clojure does give you an io! macro that you can wrap all your side effects in to
manually provide that kind of protection. If you try to use io! inside a transaction
you'll get an error at runtime.
It doesn't. What I meant by my last statement is that the transaction API forces updates to be functions of the old state, a somewhat foreign concept in python.
STM in Haskell is very natural, since Haskell already enforces pure code and side-effecting code. STM and STVar work pretty similarly to IO and IORef or ST and TVar.