(这是that question)的后续内容。
如何写lead1(Xs,Ys)
这是真的,如果Ys
是Xs
的后缀,并删除了所有前导s(s(0))
个术语。因此,现在的问题不是删除前导0
,而是删除前导s(s(0))
。
与原始问题相比,困难在于正确处理s(X)
和s(s(X))
的案例。
答案 0 :(得分:4)
list_suffix([],[]).
list_suffix([X|Xs],S) :-
if_(X=s(s(0)), list_suffix(Xs,S), S=[X|Xs]).
具有基础第一个参数的查询确定性地成功:
?- list_suffix([s(0)],S).
S = [s(0)].
?- list_suffix([s(0),s(s(0))],S).
S = [s(0), s(s(0))].
?- list_suffix([s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].
?- list_suffix([s(s(0)), s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].
如果列表包含与s / 1不同的术语,请说f(_)
第二个列表与第一个列表相同:
?- list_suffix([f(_)],S).
S = [f(_G201)].
?- list_suffix([f(_)],[]).
false.
部分实例化的列表也可以使用:
?- list_suffix([X, s(s(0)),s(0),s(s(0))],S).
X = s(s(0)),
S = [s(0), s(s(0))] ;
S = [X, s(s(0)), s(0), s(s(0))],
dif(X, s(s(0))).
最常见的查询也有效,但是以不公平的方式列出答案:
?- list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.
但是,这可以通过为目标长度/ 2添加前缀来补救:
?- length(X,_), list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = Y, Y = [_G155],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), _G79],
Y = [_G79],
dif(_G79, s(s(0))) ;
X = Y, Y = [_G155, _G158],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.
答案 1 :(得分:2)
Hiere是我对上一个问题的回答的改编。它显示使用when / 2而不是freeze / 2。冻结/ 2仅在第一个参数上遵循nonvar / 1条件。当/ 2可以遵循更复杂的条件时。
lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)).
lead([X|Y], Z) :- \+ ground(X), !, when(ground(X), lead([X|Y],Z)).
lead([s(s(0))|X], Y) :- !, lead(X, Y).
lead(X, X).
以下是一些示例运行,我正在选择类似的示例,就像我在回答中给出的答案一样。我们看到当list参数逐渐被实例化时,/ /何时适应自己的条件:
?- lead([s(0),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0), s(s(0)), s(s(0)), s(0)].
?- lead([s(s(0)),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0)].
?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(_).
X = s(_G3686),
when(ground(_G3686), lead([s(_G3686), s(s(0)), s(s(0)), s(0)], Y)).
?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(0).
X = s(0),
Y = [s(0), s(s(0)), s(s(0)), s(0)].
?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(_)).
X = s(s(_G3713)),
when(ground(_G3713), lead([s(s(_G3713)), s(s(0)), s(s(0)), s(0)], Y)).
?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].
冻结/ 2,当/ 2是校对基元时。它们的纯度在文献中有很好的记载。根据这个source,第一个带有corouts的Prolog系统是Prolog-II及其geler / 2原语。该消息来源还提到了对bootstrap约束求解器进行验证的重要性。
假设纯度是用交换性测试的,这是一个样本测试:
?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].
?- X=s(s(0)), lead([X,s(s(0)),s(s(0)),s(0)],Y).
X = s(s(0)),
Y = [s(0)].
但冻结/ 2和/ 2并非必然保证完整性,正如我在第一个回答中所写的那样,我们可能需要在最后做一些事情。在查询之后意味着我们可能有一组挣扎的目标。在约束编程中,我们将开始标记。
同样冻结/ 2,当/ 2无法通过组合目标找到早期失败,因为约束求解器可以做到。
上面的示例使用SWI-Prolog运行而没有任何导入,并且在Jekejeke Prolog中使用Minlog Extension和导入库(术语/暂停)。