EDIT:Clojure изменить обновление в возвращает NIL и dosync оленья кожа позволяют повторялись
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
ORIGINAL:
Я пытался обновить HashMap в исх следующим
(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
Что было весьма удивительно, как должно» ve возвращается
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
Ok, ты победил.
Я взглянул на: clojure.lang.Ref.alter source но не стал мудрее. (кроме того, что, на мой взгляд, alter
на самом деле не звонит apply
)
Я надеюсь, что некоторые из вас поймут это и ответят, что такое правильный код.
Что вы имеете в виду при использовании 'recur' внутри' dosync'? Вам действительно нужны вложенные транзакции? – OlegTheCat
@OlegTheCat Я на самом деле делаю да, у меня есть вложенная структура ссылок и вы хотите найти последнюю в пути, чтобы я изменил ее, проблема решена btw просто, убедившись, что вызов функции в dosync. – user5211470
@OlegTheCat btw Я согласен с вашим вопросом, если я буду запускать транзакцию, а затем повторю, это не будет хорошей идеей, так как транзакция всегда является одной (в хвостовой позиции). Я думаю, что это нормально, может быть, ее лучше если я сделал отдельную чистую функцию для поиска по пути – user5211470