开发者

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

开发者 https://www.devze.com 2022-12-21 16:35 出处:网络
The condp clauses look like this: \"plet\" (make-adj 2 \"ète\") \"iet\"(make-adj 2 \"ète\") \"nin\"(make-adj 1 \"开发者_如何学编程gne\")

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 :)

0

精彩评论

暂无评论...
验证码 换一张
取 消