Jess notes 6 自定义规则 (2)

exists不能和test CE合成在同一pattern中。

 

注意:exists正好相当于(事实上是实现了)两个嵌套的not CE;例:

(exists (A)) 相当于(not (not (A)))。人们经常写类似于(not (exists (A)))的语句,实际上相当于(not (A))

 

6.12. The 'test' conditional element.

test为首的pattern较为特殊,body不是通过使用所含的pattern而是用布尔函数与working memory相匹配。计算该函数的结果决定该pattern是否匹配。一个test pattern不匹配当且仅当计算所得函数值为FALSE;如果计算所得函数值为TRUE或其他任何值,pattern均匹配。例:

Jess> (deftemplate person (slot age)) 
Jess> (defrule example-8 
	(test (eq 4 (+ 2 2))) 
	=> 
	(printout t "2 + 2 is 4!" crlf))

 

注意:test patternnot一样,不能包含任何事先未帮定到pattern的变量。testnot可以相互组合:

(not (test (eq ?X 3)))等价于(test (neq ?X 3))

每当ruleLHS之前的(precedingpattern计算过后,test CE也要计算一下。因此以下两个rule在执行时是完全等价:

Jess> (defrule rule_1 
	(foo ?X) 
	(test (> ?X 3)) 
	=>) 
Jess> (defrule rule_2 
	(foo ?X&:(> ?X 3)) 
	=>) 

 

 

 

 

 

 

test CE作为ruleLHS的第一个pattern或在一个or CE的某分支中作为第一个pattern时,该patterninitial-fact)被插入并作为test的前继(preceding) pattern。因此该factinitial-fact)对于test条件元素的本征函数(proper functioning)来说也很重要。

 

6.12.1.不同时间方法的返回值(time-varying method returns)

test CE的一个有用的属性是:rule的结果可能在slot的内容都没有变化时改变,此时test CE是唯一有效的可以嵌入test的地方。例:假设有两个JavaAB,并且A有一个方法contains,该方法将B作为一个自变量返回一个布尔值。进一步假设对于任何给定的B对象,contains的返回值会随之改变。最后假设为这两个类分别定义了一个shadow fact template,并且为其编写相应的rule。在上述条件下,下列pattern

(A (OBJECT ?a))

(B (OBJECT ?b&:(?a contains ?b)))

是错误的。如果contains的返回值改变时,该匹配将会失效,同时Jess的内部数据结构可能会被破坏。值得注意的是,这种构造方式会导致内存溢出。

 

正确的表述上述pattern需要用到test条件元素,如下:

(A (OBJECT ?a))

(B (OBJECT ?b))

(test (?a contains ?b))

已保证在每次target和自变量相结合时,函数contains最多被调用一次影响。这样返回值的任何变化都不会产生负面影响。

 

6.12.2.何时使用test

事实上test被过度使用了,使用test通常效率没有在前一个pattern中添加同样的testslot中高。千万不要效仿以下做法:

Jess> (defrule bad-test-usage 
	(foo ?x) 
	(test (< ?x 3)) 
	=>)

 

相反,正确的做法如下:

Jess> (defrule better 
	(foo ?x&:(< ?x 3)) 
	=>)

 

仅当没有preceding pattern时使用test,或者如前所述当返回值随时间变化时。

 

6.13.'logical'条件元素

logical可用于指定fact间的逻辑依赖(logical dependencies)。在一个ruleRHS中定义的所有的fact取决于ruleLHS中的logical pattern是否匹配。如果其中任何一个匹配失效,则这些dependent fact自动失效。例:构造一个简单的fact使之依赖于(depend on)另一个简单的fact

Jess> (defrule rule-1
	(logical (faucet-open))
	=>
	(assert (water-flowing)))
TRUE
Jess> (assert (faucet-open))
<Fact-0>
Jess> (run)
1
Jess> (facts)
f-0 (MAIN::faucet-open)
f-1 (MAIN::water-flowing)
For a total of 2 facts in module MAIN.
Jess> (watch facts)
TRUE
Jess> (retract (fact-id 0))
<== f-0 (MAIN::faucet-open)
<== f-1 (MAIN::water-flowing)
TRUE

 

 

其中(water-flowing)fact在逻辑上依赖于(faucet-open)fact,所以当后者被撤销时前者也被取消了。

 

fact可以从多个源得到逻辑前提——特别的:fact有可能被声明了多次且每次都有一组不同的逻辑前提。这样的fact不能自动撤销,除非它的每一个逻辑前提都被取消了。

如果一个fact的声明没有外在(explicit)的逻辑前提,则被认为是无前提条件的(unconditionally supported)。如果一个无前提条件的fact也接受explicit logical support,则取消这些前提(support)不会导致fact的撤销。

 

如果一个或一个以上的logical CE出现在rule中,则它们必须集中于rule的所有pattern的最前面。在一个rule中,logical CE之前不能有任何其他类型的CE

 

logical CE下,shadow fact与其他fact是一样的。shadow fact可以提供逻辑前提也可以接受逻辑前提。在当前执行中,shadow fact只能提供作为一个整体的逻辑前提。在未来的Jess版本中,一个shadow fact有可能可以提供基于各个slot值的逻辑前提。

 

Jess语言函数dpendentsdependencies可以提供在fact之间查询逻辑依赖的功能。

 

6.14.'forall'条件元素

当其中每个匹配的第一个pattern时匹配forall grouping CE,其subsequent patterns也均匹配。例:

Jess> (defrule every-employee-has-a-stapler-and-holepunch 
	(forall (employee (name ?n)) 
	(stapler (owner ?n)) 
	(holepunch (owner ?n))) 
	=> 
	(printout t "Every employee has a stapler and a holepunch." crlf)

 

当所有100名雇员都满足上述两个条件时,该rule被执行(fire)。如果其中有一个雇员不满足条件,则该rule就不会执行。

你可能感兴趣的:(数据结构,F#)