简体   繁体   中英

Clojure idiomatic solution to return variables as map

I am currently learning clojure and I very much like it. However I come from an emacs-lisp background and I am still a bit confused when it comes to destructuring. Currently I receive a database-query with a lot of keys. I break them down in different variables via destructuring, and finally, after creating a couple of new values via let, I reconstruct a hash-map as a return value. The code looks like this:

(fn [{:keys [metre _id num filedate divtype section sandhi lines grammar devanagari filename notes trans sectionnumber fileauthor lang]}]
 (cond
   ;;when we have chinese
   (= lang "zh")
    (let [newgrammar (apply str (map (fn [{:keys [word position line tag] }]
                                       (str "<span class=\"dropt\">" word
                                            "<span style=\"width:500px;\"><font color=\"green\">Word:</font>" word
                                            "<br><font color=\"red\">Function:</font> " tag
                                            "<br><font color=\"blue\">Meaning:</font> " (db/get-chindic-meaning word tag)
                                            "</span></span>")) grammar)) 
          newtrans (first (map #(last (last %)) trans))]              
      (hash-map :metre metre :id _id :num num :filedate filedate :divtype divtype :section section :sandhi sandhi :lines lines :grammar newgrammar :devanagari devanagari :filename filename :notes notes :trans newtrans :sectionnumber sectionnumber :fileauthor fileauthor :lang lang))

This is just one extract, there are many different conditions following. So there is a lot of code wich feels totally unnecessary to me. I guess this is ugly and certainly not the way it should be. Any suggestions on how to do this right? Any help would be deeply appreciated!

you can capture the whole map this way:

user> (defn my-fun [{:keys [a b c d e] :as params-map}]
    (assoc params-map
           :a 200
           :b 100))
#'user/my-fun
user> (my-fun {:a 1 :b 2 :c 3 :d 4 :e 5})
{:a 200, :b 100, :c 3, :d 4, :e 5}

so you just update some specific values in a map, without redefining it. also take a look at update , it might be useful in this case

as for me, I would rewrite your fn like this: (move out some functions and use update )

(defn update-grammar [grammar]
  (apply str (map (fn [{:keys [word position line tag] }]
                    (str "<span class=\"dropt\">" word
                         "<span style=\"width:500px;\"><font color=\"green\">Word:</font>" word
                         "<br><font color=\"red\">Function:</font> " tag
                         "<br><font color=\"blue\">Meaning:</font> "     (db/get-chindic-meaning word tag)
                         "</span></span>")) grammar)))

(defn update-trans [trans] (first (map #(last (last %)) trans)))

(fn [{:keys [metre _id num filedate divtype section 
             sandhi lines grammar devanagari filename 
             notes trans sectionnumber fileauthor lang]
      :as params-map}]
 (cond
   ;;when we have chinese
   (= lang "zh")
   (-> params-map
       (update :grammar update-grammar)
       (update :trans update-trans))

you see, now you can even remove grammar and trans from :keys vector, as you don't need them anymore

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM