1

I am using ClojureScript to detect which browser-specific version of 'requestAnimationFrame' method is defined. I use the following code:

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

This works fine, and it's not terrible, but I would really like to be able to put the method names in a list, i.e.

'(requestAnimationFrame webkitRequestAnimationFrame ...)

And then call a macro for each symbol in the list to generate the anonymous function code.

I would like something to work like so:

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

But I played around with macros for a while, and was unable to achieve this effect. Part of the problem is that method names and the dot notation work strangely, and I'm not even sure if this is possible.

Any tips to get this working? Thanks!

2
  • Unless I'm terribly misreading your code, you'll always return the setTimeout function whenever the first element of options is nil. Commented Mar 30, 2012 at 6:28
  • @PhilipK Looks like it would, but it doesn't. The result of calling the functions in options is undefined if they don't exist, NOT nil. It won't be nil until the list is empty. Commented Mar 31, 2012 at 17:12

1 Answer 1

2

Remember that javascript objects are also associative hashes, so something like this should work without resorting to macros (untested)....

(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)))
Sign up to request clarification or add additional context in comments.

1 Comment

Ah hah, that's an important trick I didn't know! I didn't realize they could be accessed as a dictionary. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.