我已经写了一些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
?
答案 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
的第二个条款都匹配,这就是你在那里获得empty
和item3
的原因。 Prolog很乐意将两个变量统一到相同的值,并且这里没有任何内容可以阻止BuildItem
和H
引用相同的值。您需要明确告诉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对你的问题做了很好的解释。掌握基本的列表处理任务非常重要!