В ближайшем будущем, как я могу оценить аргументы макроса из другого макроса? - PullRequest
8 голосов
/ 10 марта 2011

У меня есть два макроса. Первый принимает символ как единственный параметр (потому что он передается в def, который нуждается в символе). Вторая функция принимает список символов и должна вызывать первый для каждого символа отдельно.

(defmacro m1 [s]
  '(let [f# ... dynamic function definition ...]
      (def ~s f#))

Второй макрос должен взять список символов и передать их первому, но я не могу заставить его работать. Лучшее, что я мог придумать, было следующее:

(defmacro m2 [symbols]
   `(for [s# ~symbols] (eval (read-string (str "(name.of.current.namespace/m1 " s# ")")))))

, который заставляет s# быть оцененным до того, как он будет передан первому макросу. Он также вызывается со списком строк, а не со списком символов.

Это полезно для библиотеки, которую я использую, для которой все функции в библиотеке принимают одинаковые два первых параметра. Я пытаюсь создать функции-оболочки в своем пространстве имен для некоторых функций, которые автоматически предоставляют первые два значения параметров, которые являются общими для всех из них.

Есть идеи по улучшению этого?

1 Ответ

8 голосов
/ 10 марта 2011

Обычно, когда вы спрашиваете, как заставить два макроса взаимодействовать, ответ не состоит в том, чтобы сделать их обоими макросами.Я думаю, что мое сообщение в блоге о макросах макросов поможет прояснить ситуацию.Для этой конкретной ситуации я бы, вероятно, объединил два предложения из комментариев:

(defmacro build-simpler-functions [& names]
  (cons 'do
        (for [name names]
          `(def ~(symbol (str "simple-" name))
             (partial ~name 5 10))))) ; if you always pass 5 and 10

(build-simpler-functions f1 f2)

Это расширится до

(do
  (def simple-f1 (clojure.core/partial f1 5 10))
  (def simple-f2 (clojure.core/partial f2 5 10)))

, что в основном похоже на то, что вы хотите.

Редактировать: если аргументы, которые вы «всегда» передаете, отличаются для каждой функции, вы можете сделать это:

(defmacro build-simpler-functions [& names]
  (cons 'do
        (for [[name & args] names]
          `(def ~(symbol (str "simple-" name))
             (partial ~name ~@args)))))

(build-simpler-functions [f1 5 10] [f2 "Yo dawg"]) ; expansion similar to the previous
...