Tyler Diaz
Tyler Diaz

Reputation: 132

Clojure map destructuring in functions that require a single key

I've currently implemented a way to sort by a deep key in a map like so:

(sort-by #(get-in % [:layer :order]) [{:layer {:order 1} {:layer {:order 2}])

I was wondering if there was a way to do this using map destructuring? Is that available for functions outside of let and parameter definition? An example of what I'm wondering is possible:

(sort-by {:layer {:order}} [{:layer {:order 1} {:layer {:order 2}])

Upvotes: 1

Views: 78

Answers (2)

birdspider
birdspider

Reputation: 3074

I don't think so because sort-by needs a value extraction function (keyfn)

(that is unless you want to sort entries directly by themself)

user=> (doc sort-by)
-------------------------
clojure.core/sort-by
([keyfn coll] [keyfn comp coll])
 Returns a sorted sequence of the items in coll, where the sort
 order is determined by comparing (keyfn item).  If no comparator is
 supplied, uses compare.  comparator must implement
 java.util.Comparator.  If coll is a Java array, it will be modified.
 To avoid this, sort a copy of the array.

EDIT: what you can do is "simulate" get-in via compose and keyword lookups as in

(sort-by (comp :a :c) [ {:c {:a 3}} {:c {:a 2}} ])

Upvotes: 0

TheQuickBrownFox
TheQuickBrownFox

Reputation: 10624

As far as I'm aware, you can only destructure within a let binding or function binding. This is how you might do it with nested map destructuring:

(sort-by (fn [{{o :order} :layer}] o)
         [{:layer {:order 2}}
          {:layer {:order 1}}])

I don't think that's any clearer, though. Since keywords are functions, you could also use plain old function composition:

(sort-by (comp :order :layer)
         [{:layer {:order 2}}
          {:layer {:order 1}}])

Upvotes: 1

Related Questions