通过 Clojure 中的变量将数据传递给宏(脚本)
Pass data to macro via variable in Clojure(Script)
有什么技巧可以在不直接传递数据或不使用 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)
如果您的 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)))
它适用于任何 data
序列,无论是本地的还是全局的,文字的还是生成的
有什么技巧可以在不直接传递数据或不使用 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)
如果您的 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)))
它适用于任何 data
序列,无论是本地的还是全局的,文字的还是生成的