Clojure: Is it possible to make a macro to create the two elements in a single condp clause?

clojure, macros

Solution

`condp` has built-in functionality to support this kind of thing:

(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)` is a binary function which checks if its arguments are equal, returning the first argument if they are or `nil` otherwise.

`:>>` makes it so that the result of evaluating the predicate on `condition` and e.g. `"plet"` gets passed to the `#(make-adj ...)` function. With the above predicate this means that if `(= "plet" condition)` is `true`, then `"plet"` gets passed on to `#(make-adj ...)`. See `(doc condp)` for more info.

If this still feels like too much typing, you can create a helper function:

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

Then use it like so:

(condp #(if (= %1 %2) %1) condition
  "plet" :>> (make-adj* 2 "ète")
  ...)

Problem

The condp clauses look like this: ``` "plet" (make-adj 2 "ète") "iet" (make-adj 2 "ète") "nin" (make-adj 1 "gne") ``` I want to add the condition to the `make-adj` function call without repeating the condition twice in one line. I'd like a macro that turns this: ``` (test-make-adj "plet" 2 "ète") (test-make-adj "iet" 2 "ète") (test-make-adj "nin" 1 "gne") ``` Into this: ``` "plet" (make-adj 2 "ète" "plet") "iet" (make-adj 2 "ète" "iet") "nin" (make-adj 1 "gne" "nin") ```

Original source