2015-02-24 13 views
2

將切割(!)放在子句的開頭是什麼意思?削減一個子句的開始以及「切割」,「!」和「失敗」之間的關係

p(X,Y) :- !, q(X), r(X,Y). 

什麼是!fail以及如何之間的區別是,他們有關係嗎?

謝謝。
我在想fail,這個謂詞就會「失敗」,而不是不回溯?只是想確定:)

+2

是的。 '失敗'意味着*失敗*。 :)這意味着它會回溯。但是'!'意味着* cut *並且意味着它不會在該條款中的這一點上進一步回溯。如果你的例子是一個單獨的子句謂詞,那麼它不會做任何事情,因爲沒有任何東西可以回溯到任何地方。但是如果在你展示的那個之後有另一個'p(X,Y): - s(X,Y)*',那麼它將不會由於先前條款的削減而行使只有參數變量,並且在第二個子句之前總是匹配一個'p(X,Y)'查詢)。 – lurker 2015-02-24 13:29:15

+2

你應該得到很好的Prolog書籍(比如*由Clocksin和Mellish編寫的Prolog *的介紹性材料,或* Sterling和Shapiro的Prolog * Art),因爲他們很全面地解釋了這些概念。 :) – lurker 2015-02-24 13:32:18

+0

好的非常感謝,我實際上已經下載,但沒有機會閱讀它大聲笑,但一定會讀它! – 2015-02-24 21:32:15

回答

4

通常,當你想確保在某個變量實例組合上沒有回溯時使用它。爲了展示一些代碼(借用the SWI-Prolog implementation一點:

read_lines(In, Ls) :- 
    read_line_to_codes(In, Codes), 
    read_lines_rest(Codes, In, Ls). 

read_lines_rest(end_of_file, _, []) :- !. 
read_lines_rest(Codes, In, [Codes|Rest]) :- 
    read_line_to_codes(In, New_codes), 
    read_lines_rest(New_codes, In, Rest). 

現在,隨着這些謂詞定義,你可以讀取輸入流(文件,例如)以行的列表,我們正在使用read_line_to_codes/2library(readutil)它將統一其第二個參數與表示線,或者在輸入端的端部的原子end_of_file代碼的列表。

read_lines_read/3第一個子句,我們使用統一的謂詞定義的頭部。我們以「需求「,如果我們希望謂詞被考慮,那麼第一個參數必須是原子end_of_file當(在en d的輸入)此子句成功,則不會考慮定義的第二個子句中的其他可能解決方案,並且謂詞成功,在第三個參數中關閉列表。

這是用來:

?- open('shortcut.pl', read, In), read_lines(In, Ls), forall(member(L,Ls), format("~s~n", [L])). 
read_lines(In, Ls) :- 
    read_line_to_codes(In, Codes), 
    read_lines_rest(Codes, In, Ls). 

read_lines_rest(end_of_file, _, []) :- !. 
read_lines_rest(Codes, In, [Codes|Rest]) :- 
    read_line_to_codes(In, New_codes), 
    read_lines_rest(New_codes, In, Rest). 
% variable instantiations 

你應該注意到,謂詞成功一次。嘗試刪除第一個子句中的剪切以查看會發生什麼。

至於fail,是的,它使謂詞失敗(不成功)。此時,如果還有任何選擇點,Prolog將回溯到最近的一個。

+0

感謝您的解釋,現在非常清楚! – 2015-02-24 21:33:35