Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it possible to pass in key value pairs to a function that destructures a map?

I thought I understood destructuring, but I was reading a clojure blog and this confused me. If you have a function written like:

(defn f [& {:keys [foo bar]}] 
  (println foo " " bar))

Why can you call it like this:

(f :foo 1 :bar 2)

My first thought was that my function was supposed to be called like this:

(f {:foo 1 :bar 2})
IllegalArgumentException No value supplied for key: {:foo 1, :bar 2}  clojure.lang.PersistentHashMap.createWithCheck (PersistentHashMap.java:89)

But obviously that doesn't work. I think this has something to do with the way & works. But I always thought that the thing after it is a vector and therefore you'd have to destructure anything after it like a vector.

Can someone explain to me how/why this definition works the way it does? Thanks

like image 531
Daniel Kaplan Avatar asked May 17 '13 06:05

Daniel Kaplan


1 Answers

The & and destructuring form work sequentially:

  • The & gathers any arguments after it into a collection
  • The map destructuring form then takes the collection, makes a map out of it if required and binds the names to the keys listed in the vector.

The vector in the map destructuring form is just syntax used to build the desctructuring/binding and does not imply anything aobut the input form

The without the & in the defn the second form will work and the first will not.
With the & the first form will work and the second will not.

like image 114
Arthur Ulfeldt Avatar answered Sep 30 '22 16:09

Arthur Ulfeldt