Есть ли способ встроенной функции, которая передается в макрос? - PullRequest
0 голосов
/ 07 декабря 2018

Например, я могу написать макрос следующим образом:

(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 голосов
/ 07 декабря 2018

Относительно вопроса, который вы на самом деле задали, я бы сказал: не делайте этого.Встраивание - это одна из вещей, которую 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)))))
0 голосов
/ 07 декабря 2018

Я новичок в 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)
...