通过Clojure(脚本)中的变量将数据传递给宏

通过Clojure(脚本)中的变量将数据传递给宏,clojure,macros,clojurescript,Clojure,Macros,Clojurescript,在不直接传递数据或使用eval的情况下,是否有任何技巧可以实现这一点 (defmacro pair-defs [data] (cons 'do (for [[k v] data] `(def ~k ~v)))) (def data '((a 1) (b 2) (c 3))) (pair-defs data) 如果在宏调用之前在命名空间中定义了数据变量,则可以使用一些命名空间操作函数按名称解析其值: (defmacro pair-defs [data] `(do ~

在不直接传递数据或使用eval的情况下,是否有任何技巧可以实现这一点

(defmacro pair-defs [data]
  (cons 'do
    (for [[k v] data]
      `(def ~k ~v))))

(def data '((a 1) (b 2) (c 3)))
(pair-defs data)

如果在宏调用之前在命名空间中定义了
数据
变量,则可以使用一些命名空间操作函数按名称解析其值:

(defmacro pair-defs [data]
  `(do ~@(for [[k v] @(ns-resolve *ns* data)]
           `(def ~k ~v))))

user> (def data [['a 10] ['b 20]])
#'user/data

user> (pair-defs data)
#'user/b
或者通过变量名处理文本数据和数据:

(defmacro pair-defs [data]
  (let [dt (if (symbol? data) @(ns-resolve *ns* data) data)]
    `(do ~@(for [[k v] dt]
             `(def ~k ~v)))))
调用扩展到所需的形式:
(do(def a 10)(def b 20))

因此,在不使用诸如
eval
之类的肮脏技巧的情况下解析名称空间val是完全可能的,但我发现这是一种不必要的宏用法。例如,您的任务很容易被普通函数调用替换

(defn pair-defs1 [data]
  (doseq [[k v] data]
    (intern *ns* k v)))
它可以处理任何
数据
序列,无论是本地的还是全局的、文本的还是生成的