使用ClojureScript宏生成javascript方法调用代码?

时间:2012-03-27 17:28:39

标签: html5 canvas macros clojure clojurescript

我正在使用ClojureScript来检测定义了哪个特定于浏览器的'requestAnimationFrame'方法版本。我使用以下代码:

(defn animationFrameMethod []
  (let [window (dom/getWindow)
        options (list #(.-requestAnimationFrame window)
                      #(.-webkitRequestAnimationFrame window)
                      #(.-mozRequestAnimationFrame window)
                      #(.-oRequestAnimationFrame window)
                      #(.-msRequestAnimationFrame window))]
    ((fn [[current & remaining]]
       (cond
        (nil? current) #((.-setTimeout window) % (/ 1000 30))
        (fn? (current)) (current)
        :else (recur remaining)))
     options)))

这很好用,并不是很糟糕,但我真的希望能够将方法名称放在一个列表中,即。

'(requestAnimationFrame webkitRequestAnimationFrame ...)

然后为列表中的每个符号调用一个宏来生成匿名函数代码。

我想要像这样工作:

user> (def name webkitRequestAnimationFrame)
user> (macroexpand '(macros/anim-method name window))
#(.-webkitRequestAnimationFrame window)

但是我玩了一段时间的宏,并且无法实现这种效果。部分问题是方法名称和点符号工作奇怪,我甚至不确定这是否可行。

有任何提示让这个工作?谢谢!

1 个答案:

答案 0 :(得分:2)

请记住,javascript对象也是关联哈希值,因此像这样的东西应该可以在不使用宏(未经测试)的情况下工作....

(def method-names ["requestAnimationFrame"
                   "webkitRequestAnimationFrame"
                   "mozRequestAnimationFrame"
                   "oRequestAnimationFrame" 
                   "msRequestAnimationFrame"])

(defn animationFrameMethod []
  (let [window (dom/getWindow)
        options (map (fn [n] #(aget window n)) method-names)]
    ((fn [[current & remaining]]
       (cond
        (nil? current) #((.-setTimeout window) % (/ 1000 30))
        (fn? (current)) (current)
        :else (recur remaining)))
     options)))