昨天 的调试信息有点迷惑,写个简单例程再体验一下:

(deftemplate 猜的
   (slot 数))

(defrule 旁白
   =>
   (println "想了个数,猜是几?"))

(defrule 猜数
  (declare (salience -5))
   (not (猜的))
   =>
   (print "猜吧:")
   (assert (猜的 (数 (string-to-field (readline))))))

(defrule 猜中
  ?所猜 <- (猜的 (数 ?数))
  (test (= 5 ?数))
  =>
  (retract ?所猜)
  (print "猜中了!")
  (halt))

(defrule 没猜中
  ?所猜 <- (猜的 (数 ?数))
  (test (<> 5 ?数))
  =>
  (retract ?所猜))

运行效果:

CLIPS> (run)
想了个数,猜是几?
猜吧:3
猜吧:4
猜吧:5
猜中了!

调试

matches 两个条件相反的规则,输出里除了 Activations 以外一样。看来 test 条件不算在模式列表中。

CLIPS> (run)
想了个数,猜是几?
猜吧:4
Breaking on rule 没猜中.
CLIPS> (matches 没猜中)
Matches for Pattern 1
f-1
Activations
f-1
(1 0 1)
CLIPS> (ppfact 1)
(猜的 
   (数 4))
CLIPS> (matches 猜中)
Matches for Pattern 1
f-1
Activations
 None
(1 0 0)

把匹配条件合并为这样的话:

?所猜 <- (猜的 (数 ?数&:(= 5 ?数)))

?所猜 <- (猜的 (数 ?数&:(<> 5 ?数)))

调试时看到 Pattern 1 匹配不同:

CLIPS> (matches 猜中)
Matches for Pattern 1
 None
Activations
 None
(0 0 0)
CLIPS> (matches 没猜中)
Matches for Pattern 1
f-3
Activations
f-3
(1 0 1)

not 模式

将此规则改写为:

(defrule 没猜中
  ?所猜 <- (猜的 (数 ?数))
  (not (猜的 (数 5)))
  =>
  (retract ?所猜))

match 调试时,第二个模式的匹配居然是 None,看来这里的 Pattern 2 指的是 (猜的 (数 5)) 而非 (not (猜的 (数 5)))

CLIPS> (run)
猜吧:3
Breaking on rule 没猜中.
CLIPS> (matches 没猜中)
Matches for Pattern 1
f-4
Matches for Pattern 2
 None
Partial matches for CEs 1 - 2
f-4,*
Activations
f-4,*
(1 1 1)

之前获取命令,输出也类似。

希望有 ppfact 那样显示某个 Pattern 的命令,但手册里没找到。

常见报错

条件格式

开始用这样判断相等:

(defrule 猜中
  ?猜 <- (猜的 (数 ?猜的数))
  (= 猜的数 5)

报错:

[PRNTUTIL2] 介绍.clp, Line 18: Syntax Error:  Check appropriate syntax for the field field of a pattern.

ERROR:
(defrule MAIN::猜中
   ?猜 <- (猜的 (数 ?猜的数))
   (=

FALSE

加 (test )后解决。

类型错误

[ARGACCES2] Function '=' expected argument #1 to be of type integer or float.

[DRIVE1] This error occurred in the join network.
   Problem resides in associated join
      Of pattern #1 in rule 猜中

[PRCCODE4] WARNING: Execution halted during the actions of defrule '猜数'.

看语言手册后,找到字符串转符号函数:

CLIPS> (= 4 (string-to-field (readline)))
4
TRUE