在Prolog中简单附加问题

时间:2010-11-11 22:57:01

标签: prolog

几个星期前我一直在研究Prolog,而且我一直坚持的一些微不足道的事情是使用append来提出解决方案。

例如,如果我的模式匹配规则类似于

pattern( foo(X,Y), L1, L ) :-
    % some code to go through a list (where the foo-pattern is)
    % and add the pattern to the list L if it matches`

我知道追加/ 3是去这里的方式,但是...... L开始未知,即不开始,当我们开始递归列表时,它开始填充匹配的模式。但是,我总是对最初发生的事情感到困惑,即当L不是地面时。

例如,这里有一段代码,我们希望在第一个参数是可能的模式列表时得到所有匹配模式的列表:

pat([foo(X,Y)|L1], R, L) :-  
    append(foo(X,Y),R,L),
    pat(L1, R, [D|L]).
pat([_|L1], R, L2) :-
    pat(L1, R, L2).

非常感谢。

2 个答案:

答案 0 :(得分:0)

您可以使用不使用append/3的解决方案。例如,请考虑以下谓词filter/3

filter(_Pattern, [], []).
filter(Pattern, [E|Es], Matches) :-
    Pattern \= E, !,
    filter(Pattern, Es, Matches).
filter(Pattern, [E|Es], [E|Matches]) :-
    filter(Pattern, Es, Matches).

filter/3的第一个子句是基本情况,如果在第二个参数列表中没有任何东西(左)匹配,那么我们得到一个空列表。由于我们没有考虑Pattern,因此将其忽略(因此前面的_针对变量。)

filter/3的第二个条款测试Pattern是否可以统一要匹配的列表的第一个元素foo(X,Y)E运算符在无法统一的参数时会成功,因此如果成功,当我们将\=与模式匹配时,可以将其丢弃并继续(注意提交到此分支的测试后的剪切E)。

!的最后一个(第三个)子句依赖于第二个子句,因为它只是将filter/3传递给最后一个参数列表E,假设它Matches匹配,因为前面的子句未能确定不是匹配。请注意,我们将Pattern附加到列表中,方法是将列表结构绑定到输出,使E子列表保持未绑定状态;完整的Matches列表只有在达到基本情况后才会完全绑定,一旦我们用尽了第二个参数中匹配的术语,就将它绑定到空列表Matches,创建类似{{1}的内容每个[][E1,E2,...,En|[]]匹配模式的地方;该术语相当于列表E1

按如下方式测试此谓词给出:

En

请注意,所有与此处[E1,E2,...,En]模式一致的内容都会根据需要过滤到?- filter(foo(X,Y), [a,b,foo(x,y),c(f),foo(v(3),Z),5], L). L = [foo(x, y), foo(v(3), Z)] ; false.

最后一点注意事项:在您的代码中,调用foo(X,Y)将始终失败,因为L仅在列表上运行;您可能想要拨打append(foo(X,Y),R,L),但在这种情况下,您只需使用append/3作为简写。

编辑:为了匹配您可能匹配和过滤的可能模式列表的特定情况,这是另一个谓词,append([foo(X,Y)],R,L)

L = [foo(X,Y)|R]

请注意filter_list/3取决于我之前对filter_list(_Patterns, [], []). filter_list(Patterns, [E|Es], Matches) :- filter(E, Patterns, []), !, filter_list(Patterns, Es, Matches). filter_list(Patterns, [E|Es], [E|Matches]) :- filter_list(Patterns, Es, Matches). 的定义,并使用完全相同的策略实施:如果filter_list/3与任何filter/3都不匹配(即,这是E成功的情况,然后我们忘记Patterns并继续,否则(最后一句)我们保留它。测试给了我们:

filter(E, Patterns, [])

答案 1 :(得分:0)

我不必在你的示例代码中查找父亲而不是... append(foo(...标准追加/ 3谓词在列表上运行。append(foo(Anything), ...将不会匹配它的任何一个子句。因此你的第一个示例子句应该总是失败,第二个应该失败或起飞构建一个无限的未绑定变量列表,最终在内存耗尽时爆炸。至于你最终是什么想要在这里做,这对我来说并不是很清楚,但听起来你不想模式匹配就像在列表中找到与给定术语统一的项目。为什么你认为追加/ 3是要走的路?