3

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?

2
  • 2
    possible duplicate of Function call in -> threading macro Commented Nov 26, 2013 at 14:12
  • 1
    Thank you Alex, now I know how to fix it: (-> '(1 2 3) ((fn [x] (reverse x)))) Commented Nov 26, 2013 at 14:25

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

Comments

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.