Answers:
保持可变状态的功能语言没有错。甚至“纯”功能语言(例如Haskell)也需要保持状态才能与现实世界进行交互。Clojure之类的“不纯正”功能语言会产生副作用,其中包括变异状态。
要点是,除非您确实需要,否则功能语言会阻止可变状态。一般样式是使用纯函数和不可变数据进行编程,并且仅在需要代码的特定部分中与“不纯”可变状态进行交互。这样,您可以将其余代码库保持为“纯”。
我认为STM在功能语言中更常见的原因有很多:
我个人喜欢Clojure允许可变性的方法,但仅在可能参与STM交易的严格控制“托管引用”的情况下。语言中的其他所有内容都是“纯功能性的”。
;; define two accounts as managed references
(def account-a (ref 100))
(def account-b (ref 100))
;; define a transactional "transfer" function
(defn transfer [ref-1 ref-2 amount]
(dosync
(if (>= @ref-1 amount)
(do
(alter ref-1 - amount)
(alter ref-2 + amount))
(throw (Error. "Insufficient balance!")))))
;; make a stranfer
(transfer account-a account-b 75)
;; inspect the accounts
@account-a
=> 25
@account-b
=> 175
请注意,上面的代码是完全事务性的和原子的-读取另一个事务中的两个余额的外部观察者将始终看到一致的原子状态,即两个余额总和为200。对于基于锁的并发来说,这是一个令人惊讶的难题在具有许多交易实体的大型复杂系统中解决。
对于某些其他启发,Rich Hickey 在本视频中出色地解释了Clojure的STM