Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the Clojure -> macro with an inner function

Tags:

clojure

I'm a Clojure beginner and I want to understand the -> macro

This code works:

(-> '(1 2 3) reverse)

But this doesn't even compile and I don't know how to deal with the error message:

user=> (-> '(1 2 3) (fn [x] (reverse x)))

CompilerException java.lang.IllegalArgumentException: Parameter declaration quote should be a vector, compiling:(NO_SOURCE_PATH:1:1)

How can I fix this?

like image 1000
bert Avatar asked Dec 07 '25 00:12

bert


1 Answers

I use macroexpand and friends a lot when unexpected things start happening. If you use these here it becomes really obvious what's going on.

user=> (macroexpand-1 '(-> '(1 2 3) (fn [x] (reverse x))))
(fn (quote (1 2 3)) [x] (reverse x))

I think seeing this it's pretty obvious that the (quote (1 2 3) should not be the first arg to fn.

We can also see that the ugly double-parens approach fixes it:

user=> (macroexpand-1 '(-> '(1 2 3) ((fn [x] (reverse x)))))
((fn [x] (reverse x)) (quote (1 2 3)))

Side note that tripped me up: you have to use macroexpand-1 to get a result here. If you use macroexpand or clojure.walk/macroexpand-all it'll blow up (with your exception) after the first expansion, since fn itself is a macro, and is being called with bad syntax after the first expansion.

like image 51
overthink Avatar answered Dec 08 '25 13:12

overthink



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!