2010-11-06 182 views
9

對Prolog謂詞控制有好奇心。Prolog中的謂詞控制

假設我有一個謂詞f(A,X)和g(B)。

f(A,X):- a,b,c, g(X). 
g(B):- true. 

a - returns true 
b - returns true. 
c - returns false. 
where a,b and c are random predicates. 

我怎麼能繼續在謂語f(A,X)如果c返回false評估g(X)

回答

8

如果你的目的是要確定c是否失敗,那麼f(A,X)這樣g(X)應評估兩種:

  1. 你可以通過編碼此含義(->)和/或析取(;),
  2. f(A,X)不需要根據c來定義。假定c沒有副作用(例如,使用assert聲明數據庫事實,或者將IO打印到流中),這會改變環境並且在c失敗時不能撤銷,在這種情況下,第一個選項是優選的。

有幾個選擇使用脫節,如:

f(A,X) :- ((a, b, c) ; (a, b)), g(X). 

這個定義(以上)不依賴於c可言,但它總會執行c(只要ab成功)。該分離(;)允許PROLOG回溯嘗試執行a, b再次如果c失敗,並繼續到g(X)。請注意,這等同於:

f(A,X) :- a, b, c, g(X). 
f(A,X) :- a, b, g(X). 

爲了PROLOG不走回頭路評估f(A,X)因爲第二(相同的)頭謂詞f(A,X)的兩次每次評估,您可以選擇將切割(!)如果您的實施支持它,之後立即在c子目標的第一個子句中。因爲如果c失敗,我們不希望口譯人員承諾選擇f(A,X)條款,相反,我們希望解釋器失敗並嘗試下一個,以便有效地執行下一步忽略c並繼續處理g(X)

另外請注意,此解決方案依賴於ab沒有副作用,因爲當c失敗,ab再次執行。如果所有ab,並c有副作用,你可以嘗試使用寓意

f(A,X) :- a, b, (c -> g(X) ; g(X)). 

這也將有效地一直執行g(X)是否c失敗與否,並不會ab再次執行,如果c失敗。這個單子句定義也不會像以前的建議那樣留下選擇點。

3

我想你可以把c換成ignore/1。考慮例如

?- false, writeln('Hello World!'). 
false. 

?- ignore(false), writeln('Hello World!'). 
Hello World! 
true. 

但是如果c失敗,爲什麼要繼續?什麼是用例?

我在SWI-Prolog中測試了這段代碼,我不確定其他Prolog是否有false/0ignore/1。 後者可以這樣雖然被定義爲:

ignore(Goal) :- Goal, !. 
ignore(_). 
+0

+1問爲什麼這會有用。可移植故障謂詞是「失敗」,順便說一句。 (這是微不足道的實現:'失敗: - 0 = 1。) – 2010-11-09 09:21:29

+0

一種情況下,如果'c'失敗,你可能想繼續是'c'具有_side-effects_;有關詳細信息,請參閱我對此問題的回答。 – sharky 2010-11-09 13:38:47