如何从Prolog中的列表中选择整数?

时间:2016-05-08 07:53:34

标签: list prolog

我正在尝试在Prolog select_integers(X, L)中创建一个谓词,如果L是一个包含X中每个整数的列表,则该值为X select_integers([], []). select_integers([X|XS], L) :- integer(X), member(X, L), select_integers(XS, L). 包含多种类型的值)。

这是我到目前为止所拥有的:

false

我在这里缺少什么?如何改善这一点以获得我想要的结果? (无论我做什么,它目前都会返回{{1}}

2 个答案:

答案 0 :(得分:4)

如果我查看你的程序,我会看到integer(X)更好地被when(nonvar(X), integer(X))取代,因为它没有声明性含义。相信我。

但是现在,一旦你有一个纯程序,我们可以通过Prolog的声明属性来找到错误。

最好是直接询问Prolog,它的想法是什么:

?- select_integers(Xs, Ys).
   Xs = Ys, Ys = []  % expected success
;  *loops*

不多。循环对我们没有帮助。它只是说无论为什么,Prolog的引擎都会进入无限循环。但我们可以专门化查询。像这样:

?- Xs = [_], Ys = [_], select_integers(Xs, Ys).
   false. % unexpected failure

也许你会更喜欢Xs = [1], Ys = [1]。我只是尝试了可能的最大值。

备注我必须将XsYs限制为包含单个元素的列表。否则查询循环。

情况现在好多了,因为意外的失败意味着我们可以诊断程序。特别是,我们可以通过删除一些部分来概括程序。我发现了你的程序的这种概括:

:- initialization( ( Xs = [_], Ys = [_], select_integers(Xs, Ys) ) ).
:- op(950, fy, *).
*_.

select_integers(_/*[]*/,[]).
select_integers([X|XS],L) :-
   * when(nonvar(X), integer(X) ),
   * member(X,L),
   select_integers(XS,L).

(为了获得该片段,我将所有内容保存到文件中,将*添加到某些目标并反复说make(内置于SWI中且{{3}对于SICStus),一直在寻找目标失败的错误信息。所以我试图尽可能地从你的程序中拿走)

剩下的一切都是失败的原因。产生故障不需要其他所有东西。这可能是对或错,我们不知道。实际上罪魁祸首是L!如果你看一下从右到左阅读的规则,它会显示:

  

如果select_integers(XS,L)为真,那么:-表示select_integers([X|XS], L)符号为[]是真的。

换句话说,第二个参数将始终保持相同的长度。并且只有select_integers([],[]). select_integers([X|XS],[X|L]) :- when(nonvar(X), integer(X) ), select_integers(XS,L). ?- Xs = [_], select_integers(Xs, Ys). Xs = Ys, Ys = [_A], when(nonvar(_A), integer(_A)). % missing further answer !所以第二个参数只能是空列表。

select_integers([],[]).
select_integers([X|XS],[X|L]) :-
   when(nonvar(X), integer(X) ),
   select_integers(XS,L).
select_integers([X|XS],L) :-
   when(nonvar(X), \+integer(X) ),
   select_integers(XS,L).

?- Xs = [_], select_integers(Xs, Ys).
   Xs = Ys, Ys = [_A],
   when(nonvar(_A), integer(_A))
;  Xs = [_A], Ys = [],
   when(nonvar(_A), \+integer(_A)).

所以这个程序现在适用于所有整数的列表。但是对于不是整数的列表,它仍然失败。以下是对此的快速解决方法:

integer_t(X, T) :-
   when(nonvar(X), ( integer(X) -> T = true ; T = false ) ).

select_integers(Xs, Is) :-
   tfilter(integer_t, Xs, Is).

有更简洁的方法来表达这一点。与:

一样
when/2

在不支持freeze/2(也不是integer_t(X, T) :- functor(X,_,_), ( integer(X) -> T = true ; T = false ). )的系统中,您仍可以安全地使用:

UIApplication.sharedApplication().windows.last?.addSubview(yourSubView)

使用this module

答案 1 :(得分:0)

我认为你需要另一个案例。

case1表示空列表。

案例2,当项目是整数时,将其添加到第二个列表

案例3,当项目不是整数时,不要将其添加到第二个列表。

select_integers([],[]).
select_integers([X|XS],[X|L]) :-
 integer(X),
 select_integers(XS,L).
select_integers([X|XS],L) :-
 \+integer(X),
 select_integers(XS,L).

如果x有重复项,您可以并且可能想要更改它,以便L没有重复项。您可以使用另一个案例或单独的谓词来执行此操作。

您也可以通过查看reif内容(例如swi http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/swi/reif.pl)来使其更具关系性,例如,一个开头可能是:

int_t(X,T):-
 integer(X),
 T = true.
int_t(X,T):-
 \+integer(X),
 T = false.

 ?- tinclude(int_t,[a,b,1,2,3,4,5],X).
 X = [1, 2, 3, 4, 5] .

这不是完全关系,因为:

?- tinclude(int_t,[A,B],[A,B]).
false.

这些都不是完整的答案,但可能会帮助你。