Loops 如何将地图向量转换为一系列符号,以评估特定地图?

Loops 如何将地图向量转换为一系列符号,以评估特定地图?,loops,map,vector,macros,clojure,Loops,Map,Vector,Macros,Clojure,我是Clojure新手,使用Light Table学习宏。我的目标是将映射向量转换为def语句列表 我想转换以下数据结构: (def label-data [ {:label "lbl_first"} {:label "lbl_second"} {:label "lbl_third"} {:label "lbl_fourth"} ] ) …转换为以下def语句: (def L1 {:label "lbl_first"}) (def L2 {:label

我是Clojure新手,使用Light Table学习宏。我的目标是将映射向量转换为def语句列表

我想转换以下数据结构:

(def label-data
  [
   {:label "lbl_first"}
   {:label "lbl_second"}
   {:label "lbl_third"}
   {:label "lbl_fourth"}
  ]
)
…转换为以下def语句:

  (def L1 {:label "lbl_first"})
  (def L2 {:label "lbl_second"})
  (def L3 {:label "lbl_third"})
  (def L4 {:label "lbl_fourth"})
我知道如何创建生成单个def语句的宏:

(defmacro def-label [num]
  (let [ idx (dec num)
         symb (symbol (str "L" idx))
         datum (label-data num)
         syntax `(def ~symb ~datum)]
    syntax))
当我使用宏时

(def-label 2)
我可以看到宏生成的符号成功解析为

L2
现在,我可以概念化地创建如下所示的宏:

 (defmacro generate-def-statements-from [lbldata]

 )
但我不明白如何在def label宏上迭代4次以生成所需的多个def语句。有人能告诉我实现这个目标的最佳方法吗

事先感谢您的建议和指导。

  • 不要评估他们的论点
  • 你要评估他们的回报价值吗
  • 所以

    必须处理文字表达式

    (macroexpand 
      '(generate-def-statements-from   
        [ {: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"}))
    
    并将计算标签中的
    do
    表单的
    def

    宏将一个表达式转换为另一个表达式,因此需要生成单个表达式。这可以通过将
    def
    s包装在
    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"}))
    
    这可能不是来自许多其他语言的直觉,因为在这些语言中,定义新的顶级表单只能发生在顶级。在clojure,情况并非如此。您可以在任何级别调用def,即使是以另一种形式。请记住,is生成一个顶级变量

    如果要将其作为函数而不是宏来执行,则不能使用
    def
    ,因为它是一种特殊形式,将其第一个参数视为符号而不进行求值。幸运的是,
    intern
    与def做了相同的事情,只是它评估了它的参数:

    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"} 
    
    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"}