Jess notes 6カスタムルール(2)


existsはtest CEと同じpatternに合成できません.
 
注意:existsはちょうど二つのネストされたnot CEに相当します.例:
(exists(A))は(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 patternはnotと同じで、予め定められたpatternに助けてくれなかった変数を含んではいけません.testとnotは互いに組み合わせることができます.
(not(test(eq?X 3))は(test(neq?X 3)に等しい.)
ruleのLHSの前のpatternを計算した後、test CEも計算します.したがって、以下の二つのruleは実行時には完全に等価である.
Jess> (defrule rule_1 
	(foo ?X) 
	(test (> ?X 3)) 
	=>) 
Jess> (defrule rule_2 
	(foo ?X&:(> ?X 3)) 
	=>) 
   
 
 
 
 
test CEがruleのLHSの最初のpatternまたは一つのor CEのある分岐の中で最初のpatternとするとき、このpatternは挿入されてtestの前継とします.このfactはtest条件要素の固有関数としても重要である.
 
6.12.1.異なる時間方法の戻り値(time-varying method returns)
test CEの有用な属性は、ruleの結果がslotの内容に変化がない場合に変更される可能性があります.このときtest CEは唯一有効で、testを埋め込むことができる場所です.例:2つのJavaクラスAとBがあると仮定し、Aは、Bを引数として1つのブール値に戻す方法containsを有する.さらに、任意の所与のBオブジェクトについてcontainsの戻り値が変化すると仮定する.最後に、これらの2つのクラスにshow 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に同じtestを追加してslaotに入れません.次のようなやり方を真似してはいけません.
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間の論理依存性を指定するために使用され得る.一つのruleのRHSで定義されているすべてのfactは、ruleのLHSにおけるlocal patternが一致するかどうかに依存する.これらのdependent factは、いずれかの整合が無効になると自動的に無効になります.例:簡単なfactを作成して他の簡単な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
 
 
このうちfactは論理的にfactに依存していますので、後者が取り消されると前者もキャンセルされます.
 
factは、複数のソースから論理的な前提を得ることができる.特に、factは、複数のステートメントを受けることができ、毎回異なる論理的前提がある.このようなfactは自動的に取り消すことができません.論理前提が全部キャンセルされた場合を除きます.
外在的な論理前提がないとfactの声明は前提条件がないとされています.前提条件のないfactもexplicit logical supportを受け入れると、これらの前提を取り消すとfactの取消しにつながりません.
 
もし1つ以上のlogical CEがruleに現れるならば、それらはruleのすべてのpatternの一番前に集中しなければなりません.一つのruleでは、logical CEの前に他のタイプのCEがあってはいけません.
 
logical CEの下でshow factは他のfactと同じです.show factは論理前提を提供しても論理前提を受け入れることができます.現在の実行では、show factは全体としての論理前提しか提供できません.将来のJessバージョンでは、show factは各slot値に基づく論理前提を提供することができる.
 
Jess言語関数dpendentsとdependenciesは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人の従業員が上記の二つの条件を満たす時、このルアーは実行されます.従業員の一人が条件を満たしていないと、ルアーは実行しません.