2013-11-24 17 views
6

我是新來的prolog,並且正在試驗如何讓它在找到一個答案後停止查詢。我使用此代碼:使Prolog返回一個解決方案,並停止顯示查詢選項

member1(L,[L|_]).      
member1(L,[_|RS]) :- member1(L,RS),!.  

的結果是:「真正的」

| ?- member1(3,[3,2,3]). 

true ? a 

yes 

我迷路了,我怎麼能拿序言停止打印而只是打印「是」。我試過使用if/else構造和格式函數,但它仍然打印「true?」。有任何想法嗎?

+0

你只想要一個答案?一個'真'? Τrue表示3 *是列表[3,2,3]的成員。第二個原因是查詢在列表中再次找到它。 'member1(2,[3,2,3])''會給你一個真實的。 – Shevliaskovic

+0

如果你在第一個真(而不是';')之後按回車,它會停止回溯 – Shevliaskovic

回答

3

你正在切錯地方。

member1(L,[L|_]) :- !.     
member1(L,[_|RS]) :- member1(L,RS).  

如果 - 那麼確實對我的工作,也許你實現它不同:基本條件,它說,「一旦基地被滿足,不走回頭路任何更多的」後切? (上SWI-序言)

member1(X,[Y|RS]) :- 
    (X = Y   -> true 
    ; member1(X,RS) -> true 
    ; false 
    ) . 

束縛水飽和度也具有謂詞once/1

編輯以解釋由false指出的錯誤。

+0

你的if-then-else版本成功兩次... – false

+0

@false啊!我忽略了第一個元素匹配的明顯情況。現在修復。感謝您指出了這一點。 –

2

從你顯示的輸出中,我假設你正在使用GNU Prolog。但是,首先只是一個重要的評論:

您放置的剪切不會像您打算的那樣剪切!事實上,它甚至不會阻止有一個單一的答案。這裏有證據表明:

| ?- member1(X,[1,2,3]). 

X = 1 ? ; 

X = 2 

yes 

所以你仍然有兩個答案。作爲一個經驗法則:遞歸目標之後的切割通常會做一些意想不到的事情。

如果你堅持要有第一個答案,那就簡單地說一下once(member(X,[1,2,3]))once/1實際上也是一個削減,但相當隱蔽。完全只做一件事就被馴服了。是的,你也可以放置遞歸規則,但對於初學者來說,最好留給後面的課程。

在所有這一切的背後還有另外一點,這是不太明顯的:如果GNU Prolog的頂級shell會看到一個開放的替代方案(行話:選擇點),它會要求您提供進一步的解決方案。所以,當GNU問你更多的,它知道有些部分還有待探討,但也不能保證,那其實是有另外一個答案:

?- member(1-X,[1-a,2-b,3-c]). 

X = a ? ; 

no 

這裏,頂層看到一個開放的選擇點,因此要求如果你想進一步探索查詢。唉,這種搜索是靜脈...