Aliaksandr Kazlou
Aliaksandr Kazlou

Reputation: 3301

Clojure threading first macro -> with Math/pow or any other multiple args function

How to write in one line the following code:

(-> 10 pow9)

where pow9 is:

(def pow9 (partial #(Math/pow % 9)))

If I write (-> 10 (partial #(Math/pow % 9))) I will get back #<core$partial$fn__4228 clojure.core$partial$fn__4228@62330c23> instead, writing (-> 10 #(Math/pow % 9)) fails with CompilerException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.ISeq, compiling:(NO_SOURCE_PATH:1:1),

although (-> 10 pow9) works fine.

The more general question is how to use -> with function which accepts more than one argument, i.e. how to make this work (-> 10 #(+ % 10))?

Upvotes: 1

Views: 438

Answers (3)

Logan Buckley
Logan Buckley

Reputation: 211

If you want the anonymous function to get called with the threaded item as its argument, you need another set of parens around it:

 (-> 10 (#(Math/pow % 9)))

This is because the macro inserts the item before the function definition (or partial application, or whatever you're doing) gets evaluated.

Upvotes: 1

muhuk
muhuk

Reputation: 16085

-> inserts previous result as the first parameter, ->> inserts previous result as the last parameter.

user=> (-> 10 (Math/pow 9))
1.0E9

user=> (-> 10 ((partial #(Math/pow % 9))))
1.0E9

Note the extra parens.

Actually you don't need partial here at all:

user=> (defn pow9 [x] (Math/pow x 9))
#'user/pow9
user=> (-> 10 pow9)
1.0E9

Upvotes: 6

cfrick
cfrick

Reputation: 37008

The call simply is

user=> (-> 10 (Math/pow 9))
1.0E9

Because the -> threading macro sends the result as first param.

Upvotes: 2

Related Questions