附加Prolog未知变量

时间:2013-03-26 14:34:37

标签: prolog logic

我已经写了一些Prolog,如果它们包含在列表一中,用名为empty的原子替换列表2中的元素:

replace_build([], _Inv, _Res).

replace_build([A| B], Inv, Res) :-
    replace_build2(A, Inv, Res), replace_build(B, Inv, Res).

replace_build2(_BuildItem, [], _NewInv) :- !.

replace_build2(BuildItem, [BuildItem| T], NewInv) :-
    replace_build2(BuildItem, T, NewInv1),
    append([empty], NewInv1, NewInv).

replace_build2(BuildItem, [H| T], NewInv) :-
    replace_build2(BuildItem, T, NewInv1),
    append([H], NewInv1, NewInv).

然而,当我运行它时,我得到一个不寻常的匿名变量(这是正确的术语吗?),如下例所示:

?- replace_build([item3], [empty, item5, item1, item3, empty], X).
X = [empty, item5, item1, empty, empty|_G467]

(它也满足我不想要的,虽然希望我可以解决这个问题!)

为什么结果列表中有|_G467

2 个答案:

答案 0 :(得分:2)

问题一是这个条款:

replace_build2(_BuildItem, [], _NewInv) :- !.

您可以通过为[]添加_NewInv来解决此问题:

replace_build2(_BuildItem, [], []) :- !.

问题只是你有一个未经实例化的变量被追加到:

?- replace_build([item3], [empty, item5, item1, item3, empty], X).
X = [empty, item5, item1, empty, empty] ;
X = [empty, item5, item1, item3, empty].

你有两个答案的原因是因为replace_build2的第二个条款都匹配,这就是你在那里获得emptyitem3的原因。 Prolog很乐意将两个变量统一到相同的值,并且这里没有任何内容可以阻止BuildItemH引用相同的值。您需要明确告诉Prolog这些是不同的,因此将最终的replace_build2子句更改为:

replace_build2(BuildItem, [H| T], NewInv) :-
  BuildItem \= H,
  replace_build2(BuildItem, T, NewInv1),
  append([H], NewInv1, NewInv).

现在你只能得到你想要的解决方案:

?- replace_build([item3], [empty, item5, item1, item3, empty], X).
X = [empty, item5, item1, empty, empty] ;
false.

您也可以在某些Prolog中使用dif/2

答案 1 :(得分:2)

如果您有“列表转换”任务,并且要处理“项目一次”逻辑,则可以使用maplist / N.

然后

replace_build(Items, Inv, Res) :-
    maplist(replace_build_item(Inv), Items, Res).

replace_build_item(Inv, Item, Res) :-
    memberchk(Item, Inv) -> Res = empty ; Res = Item.

但是要学习Prolog,你就走在了正确的轨道上,Daniel对你的问题做了很好的解释。掌握基本的列表处理任务非常重要!