Loops 如何将地图向量转换为一系列符号,以评估特定地图?
我是Clojure新手,使用Light Table学习宏。我的目标是将映射向量转换为def语句列表 我想转换以下数据结构: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
(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"}