2017-04-01 22 views
0

CLIPS让我非常困惑。我在.clp文件中定义了一个deftemplate和一个规则。CLIPS deftemplate错误插槽类型

(deftemplate basic-ch "Basic characteristics template" 
    (slot ch-name 
     (type SYMBOL) 
     (default ?DERIVE) 
    ) 
    (slot score 
     (type INTEGER) 
     (default 1) 
     (range 1 5) 
    ) 
) 
(defrule make-ch 
    ?get-ch <- (get-ch TRUE) 
    => 
    (printout t "Enter ch name" crlf) 
    (bind ?name (read)) 
    (printout t "Enter ch score" crlf) 
    (bind ?score (read)) 
    (assert (basic-ch (ch-name ?name) (score ?score))) 
    (retract ?get-ch) 
) 

当我(断言(get-ch真))和(运行),它会提示我ch名和得分。但是,如果我为分数输入字符串,则字符串分数会被规则断言!例如:

Enter ch name 
hello 
Enter ch score 
hello 
;(basic-ch (ch-name hello)(score hello)) get asserted?! 

这怎么可能?我将分数定义为INTEGER,甚至提供了范围。我怎样才能阻止呢?

回答

2

从第11节,约束属性,基本编程指南:

两种类型的约束检查的支持:静态和动态。 启用静态约束检查时,在解析函数调用和构造时检查约束违规 。这包括 约束检查规则的LHS上的模式,当 变量在多个槽中使用时。当启用动态约束 检查时,新创建的数据对象(例如deftemplate 事实和实例)检查其槽位值是否违反约束 。实质上,当加载CLIPS程序时发生静态约束检查,并且在运行CLIPS程序时发生动态约束检查。默认情况下,启用静态约束检查为 ,禁用动态约束检查。通过使用set-static-constraint-checking 和set-dynamic-constraint-checking函数可以更改默认的 行为。

如果启用了动态约束检查,您会在运行程序出现错误:

CLIPS> (set-dynamic-constraint-checking TRUE) 
TRUE 
CLIPS> (assert (get-ch TRUE)) 
<Fact-1> 
CLIPS> (run) 
Enter ch name 
hello 
Enter ch score 
hello 

[CSTRNCHK1] Slot value hello found in fact f-2  
does not match the allowed types for slot score. 
[PRCCODE4] Execution halted during the actions of defrule make-ch. 
CLIPS> 

因为它会产生一个错误,动态约束检查是用于测试,而不是验证用户在程序执行时的输入。如果要验证使用输入,请定义一些实用方法:

CLIPS> 
(defmethod get-integer ((?query STRING)) 
    (bind ?value FALSE) 
    (while (not (integerp ?value)) 
     (printout t ?query " ") 
     (bind ?value (read))) 
    ?value) 
CLIPS> 
(defmethod get-integer ((?query STRING) (?lower INTEGER) (?upper INTEGER)) 
    (bind ?value FALSE) 
    (while (or (not (integerp ?value)) (< ?value ?lower) (> ?value ?upper)) 
     (printout t ?query " (" ?lower " - " ?upper ") ") 
     (bind ?value (read))) 
    ?value) 
CLIPS> (get-integer "Pick an integer:") 
Pick an integer: hello 
Pick an integer: 3 
3 
CLIPS> (get-integer "Pick an integer" 1 5) 
Pick an integer (1 - 5) -1 
Pick an integer (1 - 5) hello 
Pick an integer (1 - 5) 8 
Pick an integer (1 - 5) 4 
4 
CLIPS>