Clojure 如何为宏生成表达式?

Clojure 如何为宏生成表达式?,clojure,dsl,Clojure,Dsl,由于不能将宏应用于列表,例如 ;;不起作用 (应用->[expr1 expr2 expr3]) 如何生成这样的表达式: (->expr1 expr2 expr3) 在哪里 expr1由生成(generate-expr1 f g h) expr2由生成(generate-expr2 f g h) expr3由生成(generate-expr3 f g h) 上下文 我正在尝试设计一个嵌入式DSL,例如 [“增量”“增量”“增量”] 然后将其转换为代码,例如 (fn[n](>n inc)

由于不能将宏应用于列表,例如

;;不起作用
(应用->[expr1 expr2 expr3])
如何生成这样的表达式:

(->expr1
expr2
expr3)
在哪里

  • expr1
    生成(generate-expr1 f g h)
  • expr2
    生成(generate-expr2 f g h)
  • expr3
    生成(generate-expr3 f g h)

上下文

我正在尝试设计一个嵌入式DSL,例如

[“增量”“增量”“增量”]
然后将其转换为代码,例如

(fn[n](>n inc))

您可以使用宏生成它,例如

(defmacro opfun [op-names]
  (let [m {"increment" 'inc}
        ops (map m op-names)]
    `(fn [n#] (-> n# ~@ops))))
然后

如果你需要在运行时提供你的参数列表,你可以直接解释你的结构

(defn build-eval [op-names]
  (let [m {"increment" inc}
        ops (map m op-names)]
    (fn [n] (reduce (fn [acc f] (f acc)) n ops))))

非常感谢。我刚刚开始熟悉宏,所以这可能是一个愚蠢的问题:你能在运行时使用宏吗?这些DSL数据结构是在运行时提供的,因此我需要同时生成和评估代码。许多原生Clojure功能实际上是在更原始的功能之上构建的宏。这些宏和用户定义的宏都在运行时“使用”。对于最终的能力,人们总是可以使用
eval
,尽管我无法想象DSL会需要它。
(defn build-eval [op-names]
  (let [m {"increment" inc}
        ops (map m op-names)]
    (fn [n] (reduce (fn [acc f] (f acc)) n ops))))