有没有一种方法可以将内联函数传递给宏?

时间:2018-12-07 16:07:14

标签: clojure macros

例如,我可以编写这样的宏:

(defmacro apply-one [f]
  `(~f 1))
(println (apply-one (fn [x] (+ 42 x))))
; => 43

但是宏扩展会导致额外的函数调用:

(macroexpand '(apply-one (fn [x] (+ 42 x))))
; => ((fn [x] (+ 42 x)) 1)

有没有一种方法可以“内联”传递的函数,以便:

(macroexpand '(apply-one (fn [x] (+ 42 x))))
; => (+ 42 1)

2 个答案:

答案 0 :(得分:3)

关于您实际提出的问题,我会说:不要这样做。内联是JVM做得很好的事情之一,并且您不应该使您的代码更复杂,更易读,以确保某些内容可以内联。

您原始的问题陈述(发表在评论中)有一个更干净的解决方案:不要重复任何内容!不用编写带有三个几乎相同的子句的cond表达式,而是使用cond为唯一变化的部分设置变量,然后使用您设置的变量无条件地处理其余部分

(let [compute (case command
                "turn on" (constantly true)
                "turn off" (constantly false)
                "toggle" not)]
  (doseq [x (range x1 (inc x2))
          y (range y1 (inc y2))
          :let [i (+ (* y W) x)]]
    (aset lights i (compute (aget lights i)))))

答案 1 :(得分:0)

我是Clojure的新手,所以以下解决方案对我来说既恐怖又美丽。但这仍然是一个解决方案。

(defmacro apply-one [f]
  (eval `(~f 1)))
(println (apply-one (fn [x] `(+ ~x 42))))
; => 43
(pprint (macroexpand-1 '(apply-one (fn [x] `(+ ~x 42)))))
; => (clojure.core/+ 1 42)