2014-01-08 40 views
0
append([],U,U). 
append([X|U1],U2,[W|U3]) :- **W = X** , append(U1,[X|U2],[I|Quyruk]) , 
          **W = I**, U3 = Quyruk . 

當我刪除「W是X」時,此代碼附加前兩個列表。Prolog Set List的頭

此代碼有不必要的變量,如「W是X」,但他們是關於我的問題。

當我設置的任何值之間爲 「W」 「: - 」 和 「追加...」 等「W是X」「W = 3」「W = 6」 - 返回假

爲什麼我不能在代碼中的該位置設置W的任何值,但我可以在代碼的末尾設置「W = I」?

查詢是append([1,2],[3],U).我想在這個代碼 得到[2,1,3]append([1,2,3],[4,5,6],U).我想[3,2,1,4,5,6]

append([1],[2,3],U).返回[1,2,3],當我把第一個列表的長度「1」(當第一個列表只有一個元素時)代碼是完美的;但是當我把第一個列表的長度> 1(當第一個列表有多個元素時)代碼返回false。

+0

爲什麼不只是:'my_append(L1,L2,L3): - 反向(L1,L4),追加(L4,L2,L3)。在prolog中'='不像其他語言那樣賦值。它*統一*。一旦通過統一實例化一個變量,你就不能在一個子句中改變它。所以一旦你做了'W = X',這就統一了它們,'W = I'將會一直失敗,除非'I'和'X'('I'和'W')碰巧用相同的值實例化。 – lurker

+0

append([1],[2,3],U)。 - >返回[1,2,3], 當我把第一個列表的長度「1」(當第一個列表只有一個元素時)代碼是完美的;但是當我把第一個列表的長度> 1(當第一個列表有多個元素時)代碼返回錯誤 – user3174737

回答

0

在prolog中,您不能分配變量,然後重新分配他們。變量被統一和實例化。一旦實例化,它們就不能在子句中重新實例化。所以,如果你有這樣一個條款內:

W = X, 
... 
W = I, 

然後第一W是統一的X=/2是統一的運營商)。這意味着它們或者現在都具有相同的實例化值(如果至少有一個實例化之前),或者它們的值將在後面強制爲相同的實例化。當稍後遇到W = I時,則I必須與W一致,否則該子句將失敗。如果I具有與實例W(並因此X)不同的具體值,則該子句將必然失敗。

讓我們看到它發生(請注意我的名字改爲my_append因爲Prolog的拒絕重新定義內置謂詞,append):

my_append([],U,U). 
my_append([X|U1], U2, [W|U3]) :- 
    W = X, 
    my_append(U1, [X|U2], [I|Quyruk]), 
    write('I = '), write(I), write('; W = '), write(W), nl, 
    W = I, 
    U3 = Quyruk. 

如果我們運行:

?- my_append([1], [1,2], L). 
I = 1; W = 1 

L = [1,2,3] 

yes 

生活是美好的。現在讓我們嘗試:

| ?- my_append([1,2], [3,4], L). 
I = 2; W = 2 % This will be OK 
I = 2; W = 1 % Uh oh... trouble 

no 

序言不能統一12,正如我上面描述。他們是兩個不同的價值觀。因此,謂詞由於W = I聲明而失敗。

解決的辦法是比你嘗試什麼簡單一些(儘管你很接近):

% Append empty to list gives the same list 
my_append([], U, U). 

% Append of [X|U1] and U2 is just append U1 and [X|U2] 
% Or, thought of another way, you are moving elements of the first list 
% over to the head of the second one at a time 
my_append([X|U1], U2, U3) :- 
    my_append(U1, [X|U2], U3). 

| ?- my_append([1,2,3],[4,5,6],L). 

L = [3,2,1,4,5,6] 

yes 

這樣做的實質是在你的代碼。其他變量正在阻礙(正如C.B.指出的那樣)。 :)

+0

追加([1],[2,3],U)。 - >返回[1,2,3],當我把第一個列表的長度「1」(當第一個列表只有一個元素時)代碼是完美的;但是當我把第一個列表的長度> 1(當第一個列表有多個元素時)代碼返回錯誤 爲什麼當第一個列表的長度大於1(> 1)時,代碼返回false? – user3174737

+0

@ user3174737查看我更新的答案,顯示我對失敗的解釋的示例。 – lurker

+0

@ user3174737我還添加了一個更新的解決方案。 – lurker

0

is運算符專門用於比較或統一整數。 W = I正在嘗試將W與I(無論類型)統一。當你統一WX(假設X是一個整數),你已經統一W,如果X\=I(不統一)你將返回false。

在你的例子中,W1統一,但你試着將它與2統一。

你有很多不必要的變量,這裏是一個非常簡單的實現附加的:

append([],XS,XS). 

append([X|XS],YS,[X|ZS]):- append(XS,YS,ZS). 

要了解什麼你的代碼去錯了,讓通過它

append([],U,U). 
append([X|U1],U2,[W|U3]) :- W is X , append(U1,[X|U2],[I|Quyruk]) , W = I, U3 = Quyruk . 
?-append([1,2,3],[4,5,6],U). 

我會走使用X1,X2,...來區分不同的綁定。

在第一次調用,X統一與1U1統一與[2,3]U2[4,5,6]結合。 W and U3在進入號角條款之前還沒有綁定。

W is X統一W1

append(U1,[X|U2],[I|Quyruk])正在呼叫append([2,3],[1,4,5,6],[I|Quyruk])。你已經看到你的遞歸工作不正常。

+0

當我寫入「W = X」或「W = 3」時,它又會返回false,爲什麼「W = X「假」W = I「是真的? – user3174737

+0

@ user3174737我會看看你的遞歸,以及爲什麼當你可以使用原來的變量時統一變量。比如,當你可以使用Quyruk時,你爲什麼要用'Quyruk'統一'U3'? –

+0

我是prolog的初學者,我知道最好的答案是 append([],XS,XS)。 append([X | XS],YS,[X | ZS]): - 追加(XS,YS,ZS)。 但是我正在嘗試不同的方式 – user3174737