2010-04-01 44 views
2

以下謂詞是remove(L,X,R),其中L是一個列表,X是要從列表中刪除的元素。代碼返回正確的列表,但它總是在返回之後返回false。Prolog刪除函數 - 幾乎可以工作

我找不到在運行時可以應用兩個規則的地方。

remove([],X,[]) :- !. 
remove([X|T],X,L1) :- remove(T,X,L1). 
remove([H|T],X,[H|L1]) :- \+(X==H), remove(T,X,L1). 

樣品查詢與預期的結果:

?- remove([1,2,3,4],3,R). 
R = [1, 2, 4] ; 
false. 

回答

1

http://www.cs.bris.ac.uk/Teaching/Resources/COMS30106/labs/tracer.html - SWI-Prolog有跟蹤/調試模式。在我看來,cmd行調試器比視覺調試器好。

編輯:

remove([],X,[]) :- !. 
remove([X|T],X,L1) :- !, remove(T,X,L1).   <-- cut was added 
remove([H|T],X,[H|L1]) :- remove(T,X,L1).   <-- condition was deleted 

上述代碼應好吧。雖然沒有保證。

+0

謝謝 - 我會用它來調試並發現我的問題。 – screenshot345 2010-04-01 18:58:42

+0

那麼,你會得到如上所述的結果,因爲: 當序言遞歸到元素3時,它有兩個選擇: 使用第二個謂詞或使用第三個謂詞。第二個謂詞的使用導致結果R = [1,2,4]; ...這是你想要的。但是使用第三個謂詞(當你想從SWI-prolog獲得更多結果時使用這個謂詞)會導致錯誤的結果 - 爲什麼?由於使用了謂詞頭部的統一(因此H和X具有相同的值3),然後檢查失敗的條件\ +(X == H)=>因此結果爲「假」。 – 2010-04-01 20:00:17

+0

謝謝!這太好了!我沒有意識到你可以通過其他呼叫切斷線路!我已經測試了你的代碼,它的功能非常好。 – screenshot345 2010-04-02 22:59:57

2

如果您的Prolog系統支持,您可以按如下步驟繼續保存。 使用tfilter/3和物化的不平等謂語dif/3,我們可以這樣寫:

remove(Xs0,E,Xs) :- tfilter(dif(E),Xs0,Xs). 

快速檢查,如果它的工作原理:

 
?- tfilter(dif(3),[1,2,3,4],Xs). 
Xs = [1,2,4].      % succeeds deterministically 

tfilter/3dif/3單調,所以 我們得到的聲音回答,甚至一般查詢:

?- remove([A,B,C],3,Xs). 
Xs = [  ],  A=3 ,  B=3 ,  C=3 ; 
Xs = [ C],  A=3 ,  B=3 , dif(C,3) ; 
Xs = [ B ],  A=3 , dif(B,3),  C=3 ; 
Xs = [ B,C],  A=3 , dif(B,3), dif(C,3) ; 
Xs = [A ], dif(A,3),  B=3 ,  C=3 ; 
Xs = [A, C], dif(A,3),  B=3 , dif(C,3) ; 
Xs = [A,B ], dif(A,3), dif(B,3),  C=3 ; 
Xs = [A,B,C], dif(A,3), dif(B,3), dif(C,3) ; 
false.