Clojure: можно ли создать макрос для создания двух элементов в одном условии condp? - PullRequest
4 голосов
/ 24 февраля 2010

Предложения condp выглядят так:

      "plet" (make-adj 2 "ète")
      "iet"  (make-adj 2 "ète")
      "nin"  (make-adj 1 "gne")

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

(test-make-adj "plet" 2 "ète")
(test-make-adj "iet" 2 "ète")
(test-make-adj "nin" 1 "gne")

В это:

      "plet" (make-adj 2 "ète" "plet")
      "iet"  (make-adj 2 "ète" "iet")
      "nin"  (make-adj 1 "gne" "nin")

Ответы [ 2 ]

4 голосов
/ 25 февраля 2010

condp имеет встроенную функциональность для поддержки такого рода вещей:

(condp #(if (= %1 %2) %1) condition
  "plet" :>> #(make-adj 2 "ète" %)
  "iet"  :>> #(make-adj 2 "ète" %)
  "nin"  :>> #(make-adj 1 "gne" %))

#(if (= %1 %2) %1) - это двоичная функция, которая проверяет, равны ли ее аргументы, и возвращает первый аргумент, если они есть, или nil в противном случае.

:>> делает так, чтобы результат оценки предиката составлял condition и, например, "plet" передается в функцию #(make-adj ...). С указанным выше предикатом это означает, что если (= "plet" condition) равно true, то "plet" передается #(make-adj ...). См. (doc condp) для получения дополнительной информации.

Если вам все еще кажется, что вы слишком много печатаете, вы можете создать вспомогательную функцию:

(defn make-adj* [n s]
  (fn [c] (make-adj n s c))

Тогда используйте это так:

(condp #(if (= %1 %2) %1) condition
  "plet" :>> (make-adj* 2 "ète")
  ...)
2 голосов
/ 24 февраля 2010

Сначала функция для создания одного из предложений condp

(defn test-make-adj [x num y]
  `(~x (make-adj ~num ~y ~x)))

Затем макрос для сборки предложений в выражение condp

(defmacro adj-condp [pred expr & clauses]
  `(condp ~pred ~expr
     ~@(mapcat test-make-adj clauses)))

ps: я не на своем репле, поэтому я не могу проверить это, пожалуйста, отредактируйте:)

...