2016-11-10 82 views
1

基本上,我試圖創建標準成員謂詞,以避免必須將模塊加載到我的項目中。檢查元素是否爲列表的成員

這是我的代碼到目前爲止,但不幸的是它不工作。我究竟做錯了什麼?我甚至把切運算符(!),在那裏,以確保它的工作,但它不...

/** 
* Checks if an element is part of a list 
* @param [H|T] List to evaluate 
* @param Elem Elem to check 
*/ 
memberCheckSimple([], _):- !, fail.  /* stop condition */ 
memberCheckSimple([H|T], Elem):- 
    Elem \= H,       /* check if element equals head of list and negate it */ 
    memberCheckSimple(T, Elem).   /* loop */ 
memberCheckSimple(_, _).    /* only gets here if Elem belongs to list */ 
+1

請注意,通常,參數是:'member(El,Els)'。 – false

+1

'memberCheckSimple(non_element,non_list)'成功 – false

+0

@false是的我知道,但是我所有的項目功能都是現在的另一種方式,如果我現在嘗試改變它們,我就會搞砸了。所以不妨讓它保持一致x)順便說一句,你在每一個prolog的帖子,我在這裏看到的stackoverflow! :p – Tirafesi

回答

3

一個與謂詞邏輯主要問題是整體,它是基於故障和你正試圖讓成功成爲沒有失敗的默認。這通常與你希望你的邏輯是相反的。你希望基於成功,也就是說,你想要建立描述事實真相的事實和規則。

你可以按如下方式播放它。你知道,如果元素在列表的頭部,它是列表的一個元素。所以下面是正確的:

memberCheckSimple([H|T], H). /* H is a member of [H|T] */ 

這也是真實的一個元素是一個列表的成員,如果它是表尾的成員:

memberCheckSimple([_|T], H) :- memberCheckSimple(T, H). 

這兩個規則是真的你需要。不符合上述規則之一的查詢將失敗,這正是您想要的。

現在看看你爲什麼失敗基於謂詞不工作的權利,並在故障情況下正在取得成功,這是因爲這條規則:

memberCheckSimple(_, _). 

這是說什麼是什麼的一員。你必須承認,這似乎不合邏輯(因爲它不是)。考慮到與切您事先條款:

memberCheckSimple([], _) :- !, fail. 

這防止回溯到你的「普遍適用」的條款,如果第一個參數是空列表([]),但如果其非空。例如,memberCheckSimple([a], b)最終將通過與第二個子句匹配的路徑進行失敗,然後匹配第一個子句。但是第一個條款的削減並不妨礙memberCheckSimple([a], b)在第三個條款上回溯(和成功)。您可以通過執行trace來觀察。

要完成基於失敗的方法(我將再次強調,這是對問題的錯誤解決方法,並且存在其他問題,例如不是關係型),您還需要在第二個子句中刪減:

memberCheckSimple([H|T], Elem) :- 
    Elem \= H,     /* check if element equals head of list and negate it */ 
    !, 
    memberCheckSimple(T, Elem). /* loop */ 

您在代碼中的註釋表明一個必要的思考過程。例如,你稱之爲「循環」實際上是一個「遞歸」。另外,正如另一個評論中提到的,自變量排序更自然地被稱爲列表後面的元素,因爲您已將其命名爲「成員」而不是「包含」。

+0

很好的答案。說得好。 – Enigmativity

+0

謝謝。你已經解釋了我需要知道的一切以及更多:) – Tirafesi