CLIPS中文手册 下载本文

? 字段的默认值

该部分自定义模板包含有三个单槽,分别为name, asset和age。

如果没有外部声明值被定义,则当(reset)执行后,CLIPS会插入自定义模板的默认值(deftemplate default values)。举个例子,在(clear)命令后输入prospect自定义模板结构,声明如下:

CLIPS>(assert (prospect))

CLIPS>(facts)

f-0 (initial-fact)

f-1 (prospect (name “”)(assets rich)(age 80)) For a total of 2 facts. CLIPS>

如你所见,CLIPS已经为name字段插入了string类型默认的值——“”。同样的,CLIPS也插入另两个字段的默认值。不同的类型有不同的默认符号,如对字符串STRINGl来说,空字符串为“”,对INTEGER为整数0,对FLOAT为浮点值0.0等等。关键字?DERIVE自动为槽值的类型选择合适的默认值,如对于字符串STRING类型为空字符串“”。

你可以显式声明字段的值,如下例所示:

CLIPS>(assert (prospect (age 99)(name “Dopey”)))

CLIPS>(facts)

f-0 (initial-fact)

f-1 (prospect (name “”)(assets rich)(age 80))

f-2 (prospect (name “Dopey”)(assets rich)(age 99)) For a total of 3 facts. CLIPS>

注意上面的字段输入顺序是无关紧要的,虽然它们都是命名字段。

在自定义模板中,最重要的是要认识到NUMBER不是像字符,字符串,整型和浮点型那些原始的字段类型。NUMBER是即可整型又可浮点的混合类型,这对于那些在编程中并不需要在乎哪种数字类型存储是非常有用的。NUMBER的两种类型之一指定类型如下所示:

(slot age

(type INTEGER FLOAT) (default 80)))

再见

通常,一个有N个槽的自定义模板的一般结构如下所示:

(deftemplate (slot-1) (slot-2) ?

(slot-N))

在一个自定义模板中,属性值一般被指定精确的值,而不是简单的如80或rich。举个例子,在这个自定义模板中,一个值类型被指定。

字段值可以被显式声明,也可以给出一个值的范围。allowed-values可以是任意的原始类型,如字符(SYMBOL),字符串(STRING),整型(INTEGER),浮点型(FLOAT)等。举例如下:

Deftemplate Enumerated Values Example

allowed-symbols rich filthy-rich loaded allowed-strings “Dopey”“Dorky”“Dicky” allowed-numbers 1 2 3 4.5 -2.001 1.3e-4 allowed-integers -100 53

allowed-floats -2.3 1.0 300.00056

allowed-values “Dopey” rich 99 1.e9

对于同一个自定义模板字段,同时指定其数字范围和允许值是行不通的。举个例子,如果你指定(allowed-integer 1 4 8),这与数值范围1到10的(range 1 10)是矛盾的。如果一些数字碰巧是连续的,如1,2,3,那么你可以指定一个范围(range 1 3)可以精确匹配。然而,这个范围对于allowed-integers来说是多余的了。因此,范围和允许值是互斥的,当你指定了一个范围时就不能指定允许值,反之亦然。通常,范围属性不能被用来与allowed-values,allowed-numbers,allowed-integer或allowed-floats连接。

去掉可选信息,一个规则使用到自定义模板如下所示:

CLIPS>(clear) CLIPS>

(deftemplate prospect ; 自定义模板名

(slot name ; 字段名

(default ?DERIVE)) ; 字段name的默认值

(slot assets

(default rich)) (slot age

(default 80))) CLIPS>

(defrule matrimonial_candidate

(prospect (name ?name)(asset ?net_worth)(age ?months)) =>

(printout t “Prospect: ”?name crlf

?net_worth crlf)

?months “months old” crlf))

CLIPS>(assert (prospect (name “Dopey Wonderful”)(age 99))) CLIPS>(run)

Prospect: Dopey Wonderful rich

99 months old CLIPS>

注意在声明事实的命令中,并没有指定rich的值,但是,rich的默认值还是被用在Dopey上了。

如果assets字段被指定值为poor,那么,指定值poor会重载assets的默认值rich。如下是一个关于Dopey那吝啬的侄子的例子:

CLIPS>(reset)

CLIPS>(assert (prospect (name “Dopey Notwonderful”) (assets poor)(age 95)))

CLIPS>(run)

Prospect: “Dopey Notwonderful” Poor

95 months old CLIPS>

自定义模板的模式可以像任意普通模式一样使用。举个例子,下面的规则用来消除不受欢迎的对象。

CLIPS>(undefrule matrimonial_candidate) CLIPS>(defrule bye-bye

?bad-prospect <- (prospect (assets poor)(name ?name)) =>

(retract ?bad-prospect)

(printout t “bye-bye” ?name crlf)) CLIPS>(reset)

CLIPS>(assert (prospect (name “Dopey Wonderful”)(assets rich)))

CLIPS>(assert (prospect (name “Dopey Notwonderful”)(assets poor))) CLIPS>(run)

bye-bye Dopey Notwonderful CLIPS>

多槽的使用

迄今为止我们还只是在模式中应用过单字段,上面的name,assets和age字段值均是单值。在许多类型的规则中,你也许会要用到多字段。自定义模板允许在一个多槽中使用到多槽值。

作为一个多槽的例子,假设你想将关系prospect的name写成多字段,这将在处理prospects的name部分匹配上有很大的灵活性。下面是采用了多槽和改进多字段部分匹配的自定义模板的定义。注意其中的多槽模式$?name,现在被用来与所有组成name的字段匹配。为了方便起见,同时给出一个自定义事实(deffacts)。

CLIPS>(clear)

CLIPS>(deftemplate prospect) (multislot name

(type SYMBOL)

(default ?DERIVE))

(slot assets

(type SYMBOL)

(allowed-symbols poor rich wealthy loaded) (default rich))

(slot age

(type INTEGER)

(range 80 ?VARIABLE) ; 越老越好 (default 80)))

CLIPS>(defrule happy_relationship

(prospect (name $?name)(assets ?net_worth)(age ?months)) =>

(printout t “Prospect: ”?name crlf

?net_worth crlf

?months” moths old” crlf))

CLIPS>(deffacts duck-bachelor

(prospect (name Dopey Wonderful)(assets rich)(age 99))) CLIPS>(reset) CLIPS>(run)

Prospect: (Dopey Wonderful) rich

99 months old CLIPS>

在输出中,Dopey的名字被包含在圆括号里,这表明了这是一个多槽值。如果你将多槽与单槽做比较,你会发现双引号不见了。在多槽中,name槽并不是一个字符串,CLIPS将name做为两个单独的字段Dopey和Wonderful来看。

修改字段槽值

自定义模板大大的方便了对模式中指定字段的访问,因为期望字段能被它的槽名所标定。可以利用修改(modify)行为修改指定的自定义模板中的槽来撤销并增加一个新事实。

作为一个例子,看看当单身鸭子Dopey Wonderful失去了它所有的鱼,从Donald鸭那里为它的母鸭买些香蕉什么的,下面的规则能执行什么。

CLIPS>(undefrule *) CLIPS>

(defrule make-bad-buys

?prospect <- (prospect (name $?name)

(assets rich) (age ?months))

=>

(printout t “Prospect: ”?name crlf

“rich” crlf)

?months “ months old” crlf crlf)

(modify ?prospect (assets poor))) CLIPS>

(defrule poor-prospect

?prospect <- (prospect (name $?name)

(assets poor) (age ?months))

=>

(printout t “Ex-prospect: ”?name crlf

Poor crlf

?months “ months old” crlf crlf))

CLIPS>(deffacts duck-bachelor

(prospect (name Dopey Wonderful)(asset rich)(age 99))) CLIPS>(reset) CLIPS>(run)

Prospect: (Dopey Wonderful) rich

99 months old