Prolog Set List's Head

时间:2014-01-08 19:29:37

标签: prolog

append([],U,U).
append([X|U1],U2,[W|U3]) :- **W  = X** , append(U1,[X|U2],[I|Quyruk]) , 
                            **W  = I**, U3 = Quyruk .

当我删除“W是X”时,此代码会附加前两个列表。

此代码包含不必要的变量,例如“W is X”,但它们与我的问题有关。

当我在“: - ”和“,追加......”之间将任何值设置为“W”时,如“W是X”“W = 3”“W = 6” - 返回false

为什么我不能在代码中的那个位置为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。

2 个答案:

答案 0 :(得分:0)

is运算符专门用于比较或统一整数。 W = I试图将W与I统一(不论类型)。当您使用W统一X时(假设X是整数),您已经统一W,如果X\=I(未统一),您将返回false。

在您的示例中,W1统一,但之后您尝试将其与2统一。

你有很多不必要的变量,这是一个非常简单的append实现:

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,...来区分不同的绑定。

在第一次通话中,X1统一,U1[2,3]统一,U2[4,5,6]统一。 W and U3在进入号角条款之前尚未受约束。

W is XW1统一起来。

append(U1,[X|U2],[I|Quyruk])正在调用append([2,3],[1,4,5,6],[I|Quyruk])。您应该已经看到递归无法正常工作。

答案 1 :(得分:0)

在prolog中,您不能分配变量,然后重新分配它们。变量是统一和实例化的。实例化后,它们不能在子句内重新实例化。所以,如果你在一个条款中有这个:

W = X,
...
W = I,

然后,第一个WX统一(=/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

Prolog无法统一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.指出的那样)。 :)