本页面的练习09 http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/要求创建一个将重复元素打包到子列表中的谓词。`var(A)`和执行顺序
一个直接的解决方案是简单的
pack([], []).
pack([H|T], [I|U]) :-
split(H, T, I, P),
pack(P, U).
其中分流split(Head, Tail, HeadGroup, Rest)
被定义为
split(A, [], [A], []).
split(A, [B|T], [A], [B|T]) :- A \= B.
split(A, [A|T], [A|U], B) :- split(A, T, U, B).
,工作正常且是相当多的在线与设置在上述网页的例子溶液。
该解决方案失败的地方是pack(X, [[a], [b, b]]).
这样的查询。两个解集之间的对应关系是双射的(中的每个pack(A, B)
都有一个且仅有一个B
),所以必须有更好的解决方案。
之一来解决它的办法是改变计算的顺序,帮助序言挑取决于类型参数的非无限的分支像以下这方面
pack([], []).
pack(A, B) :-
(var(A) ->
A = [H|T],
B = [I|U],
pack(P, U),
split(H, T, I, P)
; A = [H|T],
B = [I|U],
split(H, T, I, P),
pack(P, U)
).
两个问题。首先,这是令人难以置信的丑陋,所以有没有更好的方法来选择规则的顺序取决于参数类型?
其次,可能更复杂的问题,有没有一种方法来重写解决方案没有var(A)
,如果不是为什么?
纯粹的天才!有了'dif',它现在甚至可以解决疯狂的东西,比如'pack(A,[X,[b]])。 – vasily
要重新审视我以前的所有解决方案。 – vasily
是的。即使在第一个Prolog系统中,“dif/2”也是可用的,然后大部分被实现者忽略,现在在实现中又变得越来越普遍。毕竟,所有方向的推理都是关系编程的主要吸引力之一,所以使用'dif/2'来以一种合理而一般的方式来表达词项不等式。 – mat