Предположим, у меня есть следующий фрагмент (надуманного) кода Clojure:
(def c (clojure.lang.Atom. [nil nil]))
(swap! c
(fn [[x y]]
["done", (second (swap! c (fn [[x y]] [x y])))]))
Я ожидал бы, что это будет работать следующим образом:
Распаковка Clojure c
найти [nil nil]
и передать его внешнему fn
.
Внешний fn
вызывает swap!
, который распаковывает c
для поиска [nil nil]
,и передает это значение во внутренний fn
.
Внутренний fn
возвращает [nil nil]
.Внутренний вызов swap!
меняет его на новое значение c
.
Внешний fn
возвращает значение ["done" nil]
.
Внешний swap!
пытается compare-and-set!
и видит, что текущее значение c
, [nil nil]
, совпадает со старым значением [nil nil]
, поэтому он успешно заменяется ["done" nil]
.
Но на самом деле этот код зацикливается навсегда: внешний цикл продолжает повторяться.
Почему это так?Чего не хватает в моей ментальной модели?