我正在尝试在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}}
答案 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]
。我只是尝试了可能的最大值。
备注我必须将Xs
和Ys
限制为包含单个元素的列表。否则查询循环。
情况现在好多了,因为意外的失败意味着我们可以诊断程序。特别是,我们可以通过删除一些部分来概括程序。我发现了你的程序的这种概括:
:- 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.
这些都不是完整的答案,但可能会帮助你。