Odd difference between named and anonymous functions when using macro with stream

There's something missing in the macro with threads in Clojure.

I have a map with values, which are also maps, and I would like to find it as a result of another search. Let the mapping be simple {:a {:b 2}} - first I want to find the key :a , which will give {:b 2} , then look at b , the result will be 2 . The key for the second search should be the result of the function.

 ((fn [x] (get x :b)) ({:a {:b 2} } :a )) => 2 

Ok, make it more readable with a stream macro.

 (-> {:a {:b 2} } :a (fn [x] (get x :b))) 

those. apply :a as a function on the map, then apply another function. Well, this does not work: CompilerException java.lang.IllegalArgumentException: Parameter declaration :a should be a vector

Oddly enough, if an anonymous function is retrieved to a named one, then it works fine:

 (defn f [x] (get x :b)) (-> {:a {:b 2} } :af) => 2 

Or even:

 (def f (fn [x] (get x :b)) ) (-> {:a {:b 2} } :af) => 2 

Why is there a difference between how named and anonymous functions work?

+7
macros anonymous-function clojure
source share
2 answers

The thread macro sees and modifies each subform in the series before this form is evaluated, by recursively inserting the old form as the first argument for each subform.

you start with:

 (-> {:a {:b 2} } :a (fn [x] (get x :b))) 

This will:

 (-> (:a {:a {:b 2}}) (fn [x] (get x :b))) 

This will:

 (fn (:a {:b {:b 2}}) [x] (get x :b))) 

This is clearly not what you wanted.

But let's see what happens if you add extra parades around an anonymous function:

 (-> {:a {:b 2}} :a ((fn [x] (get x :b)))) (-> (:a {:a {:b 2}}) ((fn [x] (get x :b)))) (-> ((fn [x] (get x :b)) (:a {:a {:b 2}}))) ((fn [x] (get x :b)) (:a {:a {:b 2}})) 

In the last recursive macro exposure of the form -> now we have a valid code that does what you want.

+4
source share

In addition to the noise response in this particular case, you do not need a streaming macro. The idiomatic way to get a value from a nested map is get-in . eg:

 (get-in {:a {:b 2}} [:a :b]) 

=>

 2 
+3
source share

All Articles