2009-06-27 106 views
-1

我剛開始用Prolog的,我想不通,爲什麼下面,我希望它不工作。 我想創建一個謂詞,如果列表L2包含在L1中,則返回true。 這是我寫的:Prolog的謂詞問題

assert(contains (L1, L1)). 
assert(contains(L1, [X|L2]):-member(X, L1), contains(L1, L2)). 
assert(contains(L1, [])). 

我想這將是相當於「如果X‘L3 = X | L2’是L1,也L2在L1那麼真」,用含有( L1,L2)被遞歸地轉換,直到所有成員都被遍歷並且我們剩下最後一個選項,或者我們找到一個不在L1中的成員,並且它將會使謂詞失敗。

不幸的是,似乎沒有這樣的。它似乎只返回成員(X,L1)的值,所以包含([1,2,3],[1,4,5])通過,但包含([1,2,3],[4, 1,5])不。

我在做什麼錯了?

+0

您使用哪種Prolog實現?我無法在SWI-Prolog中重現您的問題(儘管它也不適用於此)。 – mercator 2009-06-27 16:41:13

+0

SWI-Prolog版本2.7.12 – 2009-06-28 09:31:03

+3

2.7.12?真?!嘗試像5.6.x或5.7.x一樣新的東西。 – Kaarel 2009-06-28 11:43:54

回答

5

我沒有完全理解你的問題,但我會寫contains/2謂詞是這樣的:

% An empty list is contained by any list 
contains(_, []). 

% If a list is not empty, then its 
% first element must be an element of L1, 
% and its tail must be contained by L1. 
contains(L1, [X | L2]) :- 
    member(X, L1), 
    contains(L1, L2). 

順便說一句,請注意,您的第一條規則(事實)

contains (L1, L1). 

語法錯誤(謂詞名稱後面不應有空格)。另外,如果更正,它會創建一個不需要的選擇點。所以,而不是刪除它。

如果你想在序言提示符下使用assert/1,然後執行

?- assert(contains(_, [])). 

Yes 
?- assert(contains(L1, [X | L2]) :- (member(X, L1), contains(L1, L2))). 

Yes 

要了解的知識基地結束了,使用listing/0

?- listing. 

:- dynamic contains/2. 

contains(_, []). 
contains(B, [A|C]) :- 
    member(A, B), 
    contains(B, C). 

Yes 

我不認爲問題與「自由變量斷言」,因爲你在你自己的答案中指出。相反,檢查你的包圍。

-2

顯然在自由變量上使用斷言可能會導致問題(至少在這個版本中),所以這就是爲什麼它行事不當。刪除斷言並使用諮詢(文件)命令解決了這個問題。