CLIPS是否有判断多字段元素匹配谓词的all/any/none函数?
CLIPS实现all/any/none谓词测试及匹配首个符合条件元素的方案
一、CLIPS的内置多字段谓词测试函数
CLIPS内置了三个函数用于多字段的谓词验证,正好对应all/any/none的需求:
(every$ <谓词函数> <多字段值>):检查多字段中所有元素都满足谓词要求(some$ <谓词函数> <多字段值>):检查多字段中至少存在一个元素满足谓词要求(notany$ <谓词函数> <多字段值>):检查多字段中没有元素满足谓词要求
谓词函数可以是CLIPS内置函数(如integerp),也可以用deffunction自定义,或者直接用lambda匿名函数。
二、解决“匹配首个大于10的元素”的问题
你当前的规则会同时匹配33和11,原因是$?b可以匹配任意长度的前缀(包括包含33的前缀),导致后续的?x会命中所有大于10的元素。要确保?x是第一个突破≤10限制的元素,必须保证$?b中的所有元素都≤10。
修正后的规则实现
方式1:使用匿名函数(简洁写法)
(deftemplate list (multislot vals)) (defrule first-high-val (list (vals $?b ?x &:(> ?x 10) $?e ) ) (test (every$ (lambda (?k) (<= ?k 10)) $?b)) => (println ?x) )
方式2:自定义谓词函数(可读性更强)
先定义一个判断元素是否≤10的函数,再在规则中调用:
(deffunction leq-10 (?num) (<= ?num 10) ) (deftemplate list (multislot vals)) (defrule first-high-val (list (vals $?b ?x &:(> ?x 10) $?e ) ) (test (every$ leq-10 $?b)) => (println ?x) )
方式3:直接在模式中添加约束
把every$的检查直接嵌入多字段的模式约束中,省去单独的test条件:
(deftemplate list (multislot vals)) (defrule first-high-val (list (vals $?b &:(every$ (lambda (?k) (<= ?k 10)) $?b) ?x &:(> ?x 10) $?e ) ) => (println ?x) )
上述三种写法都能确保:当输入(4 2 7 4 33 5 9 3 11 8 3 0)时,只有33会被匹配,因为$?b对应的前缀(4 2 7 4)全部满足≤10的要求;而如果$?b包含33,every$会返回false,规则不会被激活。
内容的提问来源于stack exchange,提问作者INEEDANSWERS
相关产品推荐
相关产品推荐

