2
\$\begingroup\$

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?

\$\endgroup\$
3
\$\begingroup\$

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

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ use of explicit fn could make life easier + it allows to put type hint before argument \$\endgroup\$ – Alex Ott Aug 4 '11 at 6:33
1
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.