确定列表是否为空

时间:2016-02-18 15:01:16

标签: list prolog

我想做一些如果|在prolog中的其他东西。以下是我的代码,Prolog将返回' R = false'如果我的输入列表不为空,它将返回“false”' false如果我的清单是空的。我错过了什么?

代码:

isEmpty([H|T],R) :- 
    length([H|T],L),
    ( L > 0 -> R = 'false'
    ;
    L =:= 0 -> R = 'true'
    ).

Prolog输出:

1 ?- isEmpty([],R).
false.

2 ?- isEmpty([1],R).
R = false.

3 ?- isEmpty([1,2,3],R).
R = false.

3 个答案:

答案 0 :(得分:7)

定义此方法的一种方法是使用统一("模式匹配"):

list_empty([], true).
list_empty([_|_], false).

如果您坚持使用if-then-else,则需要传递列表而不尝试以任何方式匹配

list_zerolength(List, Empty) :-
    length(List, Len),
    (   Len == 0
    ->  Empty = true
    ;   Empty = false
    ).

......但这不是最佳选择。如果第一个参数确实是一个列表,则两个谓词的行为相同:

?- list_empty([], R).
R = true.

?- list_empty([_], R).
R = false.

?- list_zerolength([], R).
R = true.

?- list_zerolength([_], R).
R = false.

但是,如果第一个参数不是 ground (也就是说,没有完全实例化),就会出现烦人的事情:

?- list_zerolength(L, true).
L = [] ;
ERROR: Out of global stack

所以,我们试图要求一个空列表,我们得到它;然而,Prolog坚持认为可能还有另一个答案。当我们尝试获取它时,我们会收到错误。

(额外的功劳:弄清楚会发生什么!)

谓词list_empty/2也不完美。考虑:

?- list_empty([_|a], R).
R = false.

这成功了,我们可以将答案解释为:"列表[_|a]不为空"。但是,这不是proper list

?- is_list([_|a]).
false.

使用length/2并不是一个坏主意。我们可以用它来编写一个可谓比list_empty/2更有用的谓词。我称之为list_nonempty/2以混淆情况:

list_nonempty([], false).
list_nonempty([_|T], true) :-
    length(T, _).

length/2不仅仅是查找列表的长度。它可用于生成增加长度的列表,或检查其第一个参数是否是正确的列表:

?- list_nonempty(L, NE).
L = [],
NE = false ;
L = [_G904],
NE = true ;
L = [_G904, _G907],
NE = true . % and so on

?- list_nonempty(L, false).
L = [].

?- list_nonempty([], true).
false.

?- list_nonempty([_|a], true).
ERROR: length/2: Type error: `list' expected, found `a' (an atom)

length/2未给出列表时,SWI-Prolog会抛出错误。更加致力于ISO合规性的实现应该失败。使用GNU Prolog:

?- list_nonempty([_|a], true).    
no

答案 1 :(得分:4)

我知道它的旧线程但仍然可能对使用SWI-Prolog的人有用。您可以尝试:

,而不是定义自己的规则
nth0(0, List, _).

它用于返回列表中的第一个元素,如果是空列表,则会失败。

答案 2 :(得分:2)

由于您只处理表单[H|T]的列表,因此您的子句仅匹配至少包含一个列表元素的列表。换句话说,您得到空列表的答案false,因为没有匹配的子句 - 不是因为长度为0。