【问题标题】:Prolog Set List's HeadProlog 集列表的头部
【发布时间】:2014-01-10 02:22:08
【问题描述】:
append([],U,U).
append([X|U1],U2,[W|U3]) :- **W  = X** , append(U1,[X|U2],[I|Quyruk]) , 
                            **W  = I**, U3 = Quyruk .

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

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

当我在 ":-" 和 ",append..." 之间将任何值设置为 "W" 时,例如 "W is 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。

【问题讨论】:

  • 为什么不直接:my_append(L1, L2, L3) :- reverse(L1, L4), append(L4, L2, L3).?在序言中= 不像其他语言那样分配。它统一。一旦通过统一实例化了变量,就不能在子句内更改它。因此,一旦您执行W = X,这将统一它们并且W = I 将始终失败,除非IXIW)碰巧用相同的值实例化。
  • 追加([1],[2,3],U)。 -> 返回 [1,2,3] ,当我取第一个列表“1”的长度时(当第一个列表只有一个元素时)代码是完美的;但是当我取第一个列表的长度 >1 时(当第一个列表有多个元素时)代码返回 false

标签: prolog


【解决方案1】:

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

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. 指出的那样)。 :)

【讨论】:

  • 追加([1],[2,3],U)。 -> 返回 [1,2,3] ,当我取第一个列表“1”的长度时(当第一个列表只有一个元素时)代码是完美的;但是当我取第一个列表的长度 >1 时(当第一个列表有多个元素时)代码返回 false 为什么当第一个列表的长度大于 1(>1)时代码返回 false?
  • @user3174737 查看我更新的答案,其中显示了我对失败的解释示例。
【解决方案2】:

is 运算符专门用于比较或统一整数。 W = I 正在尝试将 W 与 I 统一(无论类型如何)。当你统一WX(假设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])。您应该已经看到您的递归没有正常工作。

【讨论】:

  • 当我写 "W = X" 或 "W = 3" 时它再次返回 false ,为什么 "W = X" false "W = I" true ?
  • @user3174737 我会看看你的递归,以及当你可以使用原始变量时为什么要统一变量。比如,当你可以只使用Quyruk时,你为什么要把U3Quyruk统一起来?
  • 我是 prolog 的初学者,我知道最好的答案是 append([],XS,XS)。附加([X|XS],YS,[X|ZS]):- 附加(XS,YS,ZS)。但我正在尝试不同的方式
  • 我不是在寻找最好的解决方案,我只是想知道为什么我不能设置“W = 3”或“W = X”,后台有什么问题?我不能在代码的最后设置“W = I”,为什么一开始它返回false,但最后却没有问题
  • 要了解我的代码出了什么问题,让我们来看看 append([1,2],[3],U)。我想在 append([1,2,3],[4,5,6],U) 的这段代码中得到 [2,1,3]。我想得到 [3,2,1,4,5,6]
猜你喜欢
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
  • 2018-04-24
  • 1970-01-01
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多