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")
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")
...)
First a function to make one of the condp clauses
(defn test-make-adj [x num y]
`(~x (make-adj ~num ~y ~x)))
Then a macro to assemble the clauses into a condp expression
(defmacro adj-condp [pred expr & clauses]
`(condp ~pred ~expr
~@(mapcat test-make-adj clauses)))
ps: i'm not at my repl so i cant test this, please edit :)
精彩评论