Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(partial apply str) and apply-str in clojure's ->

If I do the following:

user=> (-> ["1" "2"] (partial apply str)) 
#<core$partial__5034$fn__5040 clojure.core$partial__5034$fn__5040@d4dd758>

...I get a partial function back. However, if I bind it to a variable:

user=> (def apply-str (partial apply str))
#'user/apply-str
user=> (-> ["1" "2" "3"] apply-str)       
"123"

...the code works as I intended it. I would assume that they are the same thing, but apparently that isn't the case. Can someone explain why this is to me?

like image 731
Jason Baker Avatar asked Apr 05 '10 01:04

Jason Baker


4 Answers

-> is a macro, so it doesn't have to follow the rules you would expect in terms of application. The macro transforms the source before the forms are evaluated. Try macroexpanding the forms:

user> (macroexpand '(-> ["1" "2"] (partial apply str)))
(partial ["1" "2"] apply str)

What are you trying to achieve here by using the '->' macro?

EDIT: Note that:

user> ((partial apply str) ["1" "2"])
"12"
like image 98
Tagore Smith Avatar answered Oct 12 '22 07:10

Tagore Smith


You don't have to do that at all.

(->> ["1" "2" "3"] (apply str))

Why not do that instead?

like image 26
Rayne Avatar answered Oct 12 '22 07:10

Rayne


The first expression, (-> ["1" "2"] (partial apply str)), expands into:

(partial ["1" "2"] apply str) which basically means:

Create a function from ["1" "2"] (which is also a function, since vectors are functions of index keys!) with the Vars apply and str already supplied as the first two arguments. This function gets printed as the weird #<core$partial...> string. Only when this function will be called will you get an IllegalArgumentException since vectors only take one integer argument, not two Var arguments.

like image 21
Michiel Borkent Avatar answered Oct 12 '22 07:10

Michiel Borkent


The Macro -> Threads the expr through the forms as second argument. In your case ends up in expanding to: (partial ["1" "2"] apply str), creating a parital function based on vector.

But you want to invoke a parital function based on apply and str on the threaded expr and thus need:

(-> ["1" "2"] ((partial apply str)))

Well: this code i quite confusing and not idiomatic Clojure.

like image 1
Jürgen Hötzel Avatar answered Oct 12 '22 08:10

Jürgen Hötzel