Передача состояния между макросами - PullRequest
0 голосов
/ 02 июля 2011

Каков наилучший способ создания набора макросов, которые обмениваются информацией друг с другом во время компиляции в Clojure?

Я ищу способ, позволяющий макросам знать, что делали предыдущие макросы, и действоватьсоответственно, например, как бы вы реализовали макросы, которые можно использовать следующим образом:

(macro-block-with-data ["A" "B" "C"]
   (process-next-data-item)    ; macro expands using "A"
   (process-next-data-item)    ; macro expands using "B"
   (process-next-data-item))   ; macro expands using "C"

Уточнения

  • Это должно происходить во время компиляции с макросамит.е. не с обычными функциями во время выполнения

1 Ответ

3 голосов
/ 03 июля 2011

Это лексически ограничено? Если это так, вы можете сделать что-то вроде следующего, который использует итераторы с сохранением состояния (хотя и уродливо).

(defmacro process-next-data-item []
  `(println "step" (.next ~'__state)))

(defmacro macro-block-with-data [dat & body]
  `(do
     (let [~'__state (.iterator ~dat)]
       ~@body)))

Как пример:

(defn test []
  (macro-block-with-data ["A" "B" "C"]
    (println "start")
    (process-next-data-item)    ; macro expands using "A"
    (println "middle")
    (process-next-data-item)    ; macro expands using "B"
    (println "almost done")
    (macro-block-with-data [ "NestedA" "NestedB" ]
      (println "starting nested")
      (process-next-data-item)
      (process-next-data-item)
      (println "done nested"))
    (process-next-data-item)
    (println "done")))

... приводит к ...

user> (test)
start
step A
middle
step B
almost done
starting nested
step NestedA
step NestedB
done nested
step C
done
nil
...