Using the min-key function in Clojure

Friday, July 08, 2011 10:18 PM

I was discussing today at work the problem of dealing with a variable length list of parameters in a typeless language.  If you explicitly declare the variable part of your parameters to be a list of strings, if someone only passes in one parameter, the compiler can check if it's a list of string or a single string and compile accordingly.  Without the type information (which ironically, includes C) you're out of luck.  It's got to assume you are dealing with a list.

So, if you've got a list and you want the smallest item in Clojure

(min [-2 1 3])

will just return [-2 1 3].  Not really a useful behaviour.  However, you can use apply to solve the problem:

(apply min [-2 1 3])

actually returns -2.  It gets trickier, though, when you're dealing with min-key.  Let's say you want the number that's closest to zero.

(min-key #(Mat­h/abs %) -2 1 3)

works, but what if you have a list?  Now you need to get creative:

(apply min-key #(Mat­h/abs %)) [-2 1 3])

This relies on the fact that apply always takes the last parameter and flattens it.  So (apply f a b [c d e]) is the same as (f a b c d e).

CORRECTION: My original solution to this was

((partial apply min-key #(Mat­h/abs %)) [-2 1 3])

which I didn't really like.  I invited alternatives in the comments, and got a superior one from Huw.  I've replaced the main text with his solution.  I've also learned a bit more Clojure, which is the point of blogging in the first place...

Technorati Tags:
Comments
Gravatar
# re: Using the min-key function in Clojure
Posted by Huw on 7/9/2011 10:00 AM
Apply works just fine, no? (apply min-key #(Math/abs %) [-2 1 3]) => 1
Gravatar
# re: Using the min-key function in Clojure
Posted by Paul // ohpauleez on 7/9/2011 5:44 PM
(apply min (map #(Math/abs %) [-2 1 3]))
and
(apply min-key #(Math/abs %) [-2 1 3])

both work just fine
Gravatar
# re: Using the min-key function in Clojure
Posted by jwmcqade on 7/11/2011 4:54 PM
@Paul - those two forms do different things:

(apply min (map #(Math/abs %) [-2 -1 3]))
=> 1
(apply min-key #(Math/abs %) [-2 -1 3])
=> -1

Something to add?

Talking sense? Talking rubbish? Something I'm missing? Let me know!

Fields denoted with a "*" are required.

 (will not be displayed)

 
Please add 5 and 4 and type the answer here:

Preview Your Comment