Почему другие потоки не видят мое обновление ссылки?

#concurrency #clojure

#параллелизм #clojure

Вопрос:

Я работаю над игрой в Clojure, используя Swing. У меня есть KeyListener для управления элементами управления, но он не обновляет ссылку.

 (def move (ref :drop))

(defn get-move 
  [block state x y moves]
  (do (println @move)
      (if (check-move @move x y block state) @move
        :nothing)))



(defn listener
  [keyevent]
  (let [c (.getKeyChar keyevent)]
   (do (println c)
      (cond (= c "j") (dosync (ref-set move :left))
            (= c "l") (dosync (ref-set move :right))
            (= c "i") (dosync (ref-set move :rotate))
            (= c "k") (dosync (ref-set move :drop))))))



(defn make-keylistener
  []
 (proxy [KeyAdapter] []
  (keyPressed [event]
            (listener event))))
  

Теперь идея заключается в том, что основная функция, которая обновляет графический интерфейс, вызывает get-move . Он проверяет, действительна ли ссылка на перемещение в игре, и если да, возвращает ее. Прослушиватель подключен к JPanel и изменяет ссылку на основе нажатия клавиши. Прослушиватель работает нормально — всякий раз, когда нажимается кнопка, он выводит символ ключа. Я могу только предположить, что это изменение ссылки. Однако get-move всегда возвращает одно и то же значение — он никогда не видит изменения @move. Я чувствую, что я неправильно понимаю что-то фундаментальное о параллелизме и состоянии в Clojure. Что я делаю не так, и есть ли более функциональный способ справиться с этим?

Спасибо!

РЕДАКТИРОВАТЬ: Та же проблема возникает, если я использую atoms.

Ответ №1:

Это не проблема параллелизма. .getkeycharвозвращает символ, который я сравнивал со строкой. Переписывание условий в (= (str c) «j») заставляет это работать.

Комментарии:

1. Итак, если вы сравниваете с символом, вы могли бы просто написать: (= c j)

2. указывает на символ? Приятно знать, я с этим еще не сталкивался.