1

Is it possible to use the "thread-first" macro if any of the required forms are part of a Javascript interop?

For example, if you wanted to group inputs in ranges of size 10, you might have something like the following:

(defn get-size [i]
  (-> i
      (/ 10)
      (.ceil js/Math)))

However, this doesn't work as presumably the result after division gets passed to .ceil as if it were a function. Wrapping the last form in extra parenthesis to try and have it evaluated as a single function expression also does not seem to work.

duncanhall
  • 11,035
  • 5
  • 54
  • 86

1 Answers1

4

-> & friends don't care whether the expressions they operate on are related to interop or not – they only see the forms as data structures and transform them according to simple rules.

The reason your example doesn't work is that it attempts to call a method called ceil on the number with js/Math as the argument rather than calling the method Math.ceil on the number:

  1. (-> i (/ 10) (.ceil js/Math))

  2. (-> (/ i 10) (.ceil js/Math))

  3. (.ceil (/ i 10) js/Math)

This would work:

(-> i (/ 10) (->> (.ceil js/Math)))

As would the anonymous function approach with the correct argument order:

(-> i (/ 10) (#(.ceil js/Math %)))

For more complex cases with initial arguments to -> more complex than just i you might find as-> quite useful.

Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212