代码之家  ›  专栏  ›  技术社区  ›  Michiel de Mare

clojure:可以用宏在一个condp子句中创建两个元素吗?

  •  4
  • Michiel de Mare  · 技术社区  · 15 年前

    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 回复  |  直到 15 年前
        1
  •  4
  •   Michał Marczyk    15 年前

    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 然后 “普莱特” 被传给 (使……) . 见 (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
  •  2
  •   Michał Marczyk    15 年前

    第一个函数,用于生成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)))
    

    附言:我不在我的回复,所以我不能测试这个,请编辑:)