I have an mail object that returns its headers as an Enumerator of Header objects, which have two methods, getName and getValue. I need to convert that to a nice Clojure map so I wrote this short function:
(defn extract-headers [message]
(reduce (fn [hs h] (conj hs {(.getName h) (.getValue h)}))
{}
(enumeration-seq (.getAllHeaders message))))
Anything to change or improve here?
3 Answers 3
You can use into
, for example:
(defn extract-headers [message]
(let [headers (enumeration-seq (.getAllHeaders message))]
(into {} (map #(vector (.getName %1) (.getValue %1)) headers))))
first, with map
you build sequence of 2-element vectors, that later is converted into map
Reading the other answer, a simple small improvement would be:
(defn extract-headers [message]
(reduce #(conj %1 {(.getName %2) (.getValue %2)})
{}
(enumeration-seq (.getAllHeaders message))))
Only to make it a little shorter.
-
\$\begingroup\$ use of explicit
fn
could make life easier + it allows to put type hint before argument \$\endgroup\$Alex Ott– Alex Ott2011年08月04日 06:33:01 +00:00Commented Aug 4, 2011 at 6:33
I rather like the into approach, I think it's more idiomatic to use a dedicated function than reduce, which is quite general. However, I think using threading is easier to read long term.
(defn extract-headers [^Mail message]
(letfn [(project [^Header h] (list (.getName h) (.getValue h)))]
(->>
message
.getAllHeaders
enumeration-seq
(map project)
(into {}))))
As you can see, I've also incorporated Alex's suggestion to use an explict fn, which avoids reflection.