(这是该问题的后续行动)。
如何写lead1(Xs,Ys)
哪个是真的,iff是去掉所有前导词Ys
的后缀。因此,这个问题现在不是删除前导s,而是关于删除前导s。Xs
s(s(0))
0
s(s(0))
与原问题相比,难点在于办案s(X)
和s(s(X))
妥善处理。
(这是该问题的后续行动)。
如何写lead1(Xs,Ys)
哪个是真的,iff是去掉所有前导词Ys
的后缀。因此,这个问题现在不是删除前导s,而是关于删除前导s。Xs
s(s(0))
0
s(s(0))
与原问题相比,难点在于办案s(X)
和s(s(X))
妥善处理。
list_suffix([],[]).
list_suffix([X|Xs],S) :-
if_(X=s(s(0)), list_suffix(Xs,S), S=[X|Xs]).
使用 ground first 参数的查询确定性地成功:
?- 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 = [] ;
.
.
.
Hiere 是对我对上一个问题的回答的改编。它显示了使用 when/2 而不是 freeze/2。freeze/2 仅遵循第一个参数的 nonvar/1 条件。when/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 参数逐渐实例化时 when/2 如何适应自己的条件:
?- 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)].
freeze/2 和 when/2 是协作原语。它们的纯度在文献中有很好的记载。根据这个来源,第一个带有 corouting 的 Prolog 系统是带有 geler/2 原语的 Prolog-II。该消息来源还提到了协程对引导约束求解器的重要性。
假设用交换性测试纯度,这里是一个示例测试:
?- 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)].
但是 freeze/2 和 when/2 不一定保证完整性,正如我在第一个答案中已经写的那样,我们可能需要在“最后”做一些事情。意味着在查询之后,我们可能有一组挣扎的目标。在约束规划中,我们将开始标记。
freeze/2 和 when/2 也不能通过组合目标来找到早期失败,约束求解器可以这样做。
上面的示例在没有导入的情况下使用SWI-Prolog运行,并且在 Jekejeke Prolog 中使用Minlog 扩展和导入库(term/suspend)。