loops - How do you transform a vector of maps into a series of symbols that eval to a particular map? -
i clojure newbie using light table learn macros. goal convert vector of maps list of def statements.
i want transform following data structure:
(def label-data [ {:label "lbl_first"} {:label "lbl_second"} {:label "lbl_third"} {:label "lbl_fourth"} ] ) ...into following def statements:
(def l1 {:label "lbl_first"}) (def l2 {:label "lbl_second"}) (def l3 {:label "lbl_third"}) (def l4 {:label "lbl_fourth"}) i know how create macro generates single def statement:
(defmacro def-label [num] (let [ idx (dec num) symb (symbol (str "l" idx)) datum (label-data num) syntax `(def ~symb ~datum)] syntax)) when utilize macro...
(def-label 2) i can see symbol generated macro resolves to...
l2 now, can conceptualize creating macro looks this:
(defmacro generate-def-statements-from [lbldata] ) but not understanding how iterate on def-label macro 4 times generate multiple def statements desired. can show me best technique accomplish objective?
thank advice , guidance, beforehand.
macros turn 1 expression 1 other expression need produce single expression. can accomplished wrapping defs in do
user> (defmacro def-label-data [label-data] `(do ~@(map #(list 'def %1 %2) (map #(symbol (str "l" %)) (range 1 (inc (count label-data)))) label-data))) #'user/def-label-data user> (macroexpand '(def-label-data [{:label "lbl_first"} {:label "lbl_second"} {:label "lbl_third"} {:label "lbl_fourth"}])) (do (def l1 {:label "lbl_first"}) (def l2 {:label "lbl_second"}) (def l3 {:label "lbl_third"}) (def l4 {:label "lbl_fourth"})) this may not intuative coming many other languages defining new top level forms can happen @ top level. in clojure not case. can call def @ level, in form. remember produces top level var.
if want do function instead of macro can't use def because special form treats it's first argument symbol without evaluating it. fortunatly intern same thing def except evaluates it's arguments:
user> (defn def-label-data [label-data] (map #(intern *ns* %1 %2) (map #(symbol (str "l" %)) (range 1 (inc (count label-data)))) label-data)) #'user/def-label-data user> (def-label-data [{:label "lbl_first"} {:label "lbl_second"} {:label "lbl_third"} {:label "lbl_fourth"} {:label "lbl_fifth"}]) (#'user/l1 #'user/l2 #'user/l3 #'user/l4 #'user/l5) user> l5 {:label "lbl_fifth"} user> l4 {:label "lbl_fourth"} user> l3 {:label "lbl_third"} user> l2 {:label "lbl_second"} user> l1 {:label "lbl_first"}
Comments
Post a Comment