CLIPS deftemplate错误的插槽类型

时间:2017-04-01 14:38:17

标签: clips expert-system

CLIPS非常困惑。我在.clp文件中定义了一个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 TRUE))和(跑步)时,它会提示我输入名称和分数。但是,如果我输入分数的字符串,则规则会断言字符串分数!例如:

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

这怎么可能?我已将得分定义为INTEGER,甚至提供了范围。我怎么能阻止这个?

1 个答案:

答案 0 :(得分:2)

基本编程指南的第11节“约束属性”:

  

支持两种类型的约束检查:静态和动态。   启用静态约束检查时,违反约束条件   在解析函数调用和构造时检查。这包括   当规则的LHS上的模式之间的约束检查   变量用于多个槽中。当动态约束时   检查已启用,新创建的数据对象(例如deftemplate   事实和实例)检查其槽值是否有约束   违法行为。本质上,静态约束检查发生在a   加载CLIPS程序并在a时发生动态约束检查   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>