РЕДАКТИРОВАТЬ:
dosync
сам создает функцию, поэтому вызовы recur
интерпретируются как вызовы, сделанные сгенерированной dosync
функцией.
Это след функции, которую я на самом деле сделал. Сделал как можно проще, я думаю.
(defn change-to-ref [ref data]
(dosync
(if-let [[new-ref new-data] (some-test @ref data)]
(recur new-ref new-data)
(alter ref f data))))
Исключение:
CompilerException java.lang.IllegalArgumentException:
Mismatched argument count to recur, expected: 0 args, got: 2
ОРИГИНАЛ:
Я пытался обновить хэш-карту в ссылке следующим образом
(def example-ref (ref {:some {:nested {:structure}}}))
(defn f [this] [this]) ;; just an example function
(sync (alter example-ref update-in [:some] f)
user=> nil
Что было довольно удивительно, так как он должен был вернуться
user=> {:some [{:nested {:structure}}]}
Итак, чем я пытался:
(update-in @example-ref [:some] f)
user=> {:some [{:nested {:structure}}]}
Но потом я прочитал, что alter
звонит apply
так:
(apply update-in @example-ref '([:some] f))
user=> {:some nil}
Итак, давайте сделаем это правильно:
(apply update-in @example-ref (list [:some] f))
user=> {:some [{:nested {:structure}}]}
Хорошо, что я понял это, но это не объясняет, почему в alter
что-то идет не так, и я все равно не могу это изменить...
(apply (fn [a b] (update-in a b f)) @example-ref '([:something]))
user=> {:some [{:nested {:structure}}]}
Это выглядит ужасно, но, по крайней мере, это работает, и я могу симулировать это на alter
:D
(sync (alter example-ref (fn [a b] (update-in a b f)) [:some])
user=> nil
Хорошо, ты выиграл.
Я просмотрел: clojure.lang .Ref.alter source, но ничего не изменилось. (кроме того, насколько я понимаю, alter
на самом деле не звонит apply
)
Я надеюсь, что некоторые из вас поймут это и ответят, какой код является правильным.
recur
внутриdosync
? Вам действительно нужны вложенные транзакции? - person OlegTheCat   schedule 07.10.2016