如何回归' prolog的价值?

时间:2016-11-23 13:38:57

标签: list prolog

我要做的是将两个列表中的元素追加到另一个列表中,最后在控制台中获取新列表的值。 我的清单是:A = [a,b]; B(对列表)= [(c,cc),(a,aa),(b,bb)] 如果第一个元素匹配pair的第一个元素(字典原则),我想添加列表B对的第二个元素。我希望所有这些元素都添加到控制台输出的空列表中。 到目前为止我所拥有的是(X将是空列表):

aa(_, [], _) :-
    true.

aa([H|T], [(A, B)|T2], X) :-
    H == A ->
        append([B], X, X2), aa([H|T], T2, X2);
        aa([H|T], T2, X).

在控制台中输入:read(X), trace,aa([a, b], [(c, cc), (a, aa), (b, bb)], X), write(X).

但是它一直返回X的[]值。如果我要求X,我怎样才能得到X2的值作为输出? 这是跟踪输出:

 Call:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
 Call:a==c
 Fail:a==c
 Redo:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
 Call:aa([a, b], [(a,aa), (b,bb)], [])
 Call:a==a
 Exit:a==a
 Call:lists:append([aa], [], _2110)
 Exit:lists:append([aa], [], [aa])
 Call:aa([a, b], [(b,bb)], [aa])
 Call:a==b
 Fail:a==b
 Redo:aa([a, b], [(b,bb)], [aa])
 Call:aa([a, b], [], [aa])
 Exit:aa([a, b], [], [aa])
 Exit:aa([a, b], [(b,bb)], [aa])
 Exit:aa([a, b], [(a,aa), (b,bb)], [])
 Exit:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
 Call:write([])
[]
 Exit:write([])

1 个答案:

答案 0 :(得分:1)

;放在一行的末尾并不是一个好主意,很容易忽略它。我更喜欢不同的格式,见下文。至于你的问题,你有append/3的错误顺序的参数。 X2是递归调用的中间结果,您希望"返回"是此X2与元素B

的组合
aa(_, [], _) :-
    true.

aa([H|T], [(A, B)|T2], X) :-
    (   H == A
    ->  append([B], X2, X), aa([H|T], T2, X2)
    ;   aa([H|T], T2, X) ).

目标append([B], X2, X)可以更清晰地写为X = [B|X2]

这解决了眼前的问题,但还不是整个谓词:

?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa|_G22] ;
false.

您将第一个参数分解为[H|T]但实际上并未对此列表进行递归,因此您永远不会在b及其对应列表中查看其对应的元素。

这是完成整个事情的简单方法:

aa([], _Pairs, []).
aa([Key|Keys], Pairs, Values) :-
    (   member((Key, Value), Pairs)
    ->  aa(Keys, Pairs, Values0),
        Values = [Value|Values0]
    ;   aa(Keys, Pairs, Values) ).

这里的主要见解是,一旦您知道Key,就可以在对话列表中查找一对(Key, Value)Value尚未绑定到值,如果列表包含第一个元素为member/2的对,则Key将对其进行实例化。这是统一的力量!

这似乎有效:

?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa, bb].

最后,您可能不希望在此之前拥有read(X),因为这意味着用户必须预测解决方案!