2010-02-24 65 views
4

的condp条款是这样的:Clojure:是否可以创建一个宏来在单个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") 

回答

4

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

首先一个功能,使condp条款

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

之一,那么宏组装条款转化为condp表达式

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

PS:我不是在我的REPL,所以我不能对此进行测试,请编辑:)

+1

我在几个补丁的代码已经编辑。除了删除两个小错误之外,我用'mapcat'替换了'(应用concat(map ...))'并根据样式调整了缩进。希望你确定。 – 2010-02-25 00:58:03

+0

是啊,多数民众赞成在:) – 2010-02-25 01:18:11

相关问题