3

次のコードについていくつか質問があります。

(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))
    
4

2 に答える 2

8

アニメーション機能で-見送りでアニメーションの前に#'が使用されるのはなぜですか?

Clojureのダイナミックな性質を示すため。

フォーム#'animationは、Clojureの可変参照型の1つであるVarです。defnマクロはVarを作成します。便宜上、関数を参照するVarを呼び出すことは、関数自体を呼び出すことと同じです。ただし、関数とは異なり、Varは変更できます。Clojure REPLで再定義#'animationして、すぐに効果を確認できます。

を使用(send-off *agent* #'animation)すると、Clojureは#'animation毎回Varの現在の値を検索します。コードが(send-off *agent* animation)代わりに使用された場合、Clojureは値を1回だけ検索し、ループを停止せずにアニメーション関数を変更することはできません。

于 2011-05-11T21:19:27.560 に答える
3

1.これは私にも少しわかりにくいですが、Richによる設計上の決定のようです。あなたが気づいたら:

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

varが関数/マクロの場所にある場合、最終的には関数またはマクロに解決されます。

2.ここで理解すべき重要なことの1つは、エージェントモデルです。エージェントは、単一の可変セルで動作するワーカーと考えることができます。そのエージェントが実行する作業のキュー(機能のキュー)があります。送信および送信は、そのキューに作業を追加します。見送りはキューに作業を追加するだけなので、すぐに戻ります。エージェントは関数をシリアルに実行するだけなので、最初のアニメーション呼び出しは次のアニメーション呼び出しを実行する前に終了する必要があります。したがって、見送りを最初に置いても最後に置いても、基本的に同じことを達成できます。

3.2つの間に目立った違いはないはずです。

于 2011-05-11T15:12:36.647 に答える