Clojure Agent вопрос - с помощью отправки - PullRequest
2 голосов
/ 11 мая 2011

У меня есть пара вопросов по поводу следующего кода:

(import 
 '(java.awt Color Graphics Dimension)
 '(java.awt.image BufferedImage)
 '(javax.swing JPanel JFrame))

(def width 900)
(def height 600) 

(defn render
 [g]
 (let [img (new BufferedImage width height 
                 (. BufferedImage TYPE_INT_ARGB))
       bg (. img (getGraphics))]
   (doto bg
      (.setColor (. Color white))
      (.fillRect 0 0 (. img (getWidth)) (. img (getHeight)))
      (.setColor (. Color red))
      (.drawOval 200 200 (rand-int 100) (rand-int 50)))
   (. g (drawImage img 0 0 nil))
   (. bg (dispose))
   ))

(def panel (doto (proxy [JPanel] []
                        (paint [g] (render g)))
             (.setPreferredSize (new Dimension 
                                     width 
                                     height))))

(def frame (doto (new JFrame) (.add panel) .pack .show))

(def animator (agent nil))


(defn animation 
  [x]
  (send-off *agent* #'animation)
  (. panel (repaint))
  (. Thread (sleep 100)))

(send-off animator animation)
  1. В функции анимации - почему #' используется перед анимацией при отправке?
  2. Почему send-off в начале анимации работает? Разве он не должен просто снова запускать функцию анимации и никогда не выполнять методы repaint и sleep?
  3. Есть ли какой-либо недостаток по сравнению с оригиналом при написании функции анимации:

    (defn animation 
      [x]
      (. panel (repaint))
      (. Thread (sleep 100))
      (send-off *agent* animation))
    

Ответы [ 2 ]

8 голосов
/ 12 мая 2011

В функции анимации - почему # используется перед анимацией при отправке?

Для демонстрации динамического характера Clojure.

Форма #'animationVar, один из изменяемых ссылочных типов Clojure.Макрос defn создает Var.Для удобства вызов Var, который ссылается на функцию, аналогичен вызову самой функции.Но Var, в отличие от функции, может измениться!Мы можем переопределить #'animation в REPL Clojure и сразу увидеть эффекты.

Использование (send-off *agent* #'animation) заставляет Clojure каждый раз искать текущее значение #'animation Var.Если бы код использовал (send-off *agent* animation) вместо этого, то Clojure посмотрел бы значение только один раз, и было бы невозможно изменить функцию анимации без остановки цикла.

3 голосов
/ 11 мая 2011

1. Это также немного неясно для меня, но похоже, что это дизайнерское решение Рича. Если вы заметили:

user=> (defn x [y] (+ y 2))
#'user/x
user=> ((var x) 3)
5

Если переменная находится в местоположении функции / макроса, она в конечном итоге преобразуется в функцию или макрос.

2. Одна важная вещь для понимания здесь - это модель агента. Агенты могут рассматриваться как работники, работающие с одной изменяемой ячейкой. Для этого агента есть очередь работы (очередь функций). отправить и отправить добавить работу в эту очередь. Поскольку отправка только добавляет работу в очередь, она немедленно возвращается. Поскольку агент выполняет только функции последовательно, первый вызов анимации должен завершиться перед выполнением следующего. Таким образом, вы достигаете в основном одного и того же, независимо от того, отправляете ли вы отправку первым или последним.

3. Между ними не должно быть заметной разницы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...