确定列表是否为空

zih*_*aow 2 list prolog

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

码:

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

Prolog输出:

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

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

3 ?- isEmpty([1,2,3],R).
R = false.
Run Code Online (Sandbox Code Playgroud)

小智 7

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

list_empty([], true).
list_empty([_|_], false).
Run Code Online (Sandbox Code Playgroud)

如果你坚持使用if-then-else,你需要传递列表而不试图以任何方式匹配它:

list_zerolength(List, Empty) :-
    length(List, Len),
    (   Len == 0
    ->  Empty = true
    ;   Empty = false
    ).
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

?- list_zerolength([_], R).
R = false.
Run Code Online (Sandbox Code Playgroud)

但是,如果第一个参数不是基础(也就是说,未完全实例化),则会发生令人讨厌的事情:

?- list_zerolength(L, true).
L = [] ;
ERROR: Out of global stack
Run Code Online (Sandbox Code Playgroud)

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

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

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

?- list_empty([_|a], R).
R = false.
Run Code Online (Sandbox Code Playgroud)

这成功了,我们可以将答案解释为:"列表[_|a]不为空".但是,这不是一个正确的清单!

?- is_list([_|a]).
false.
Run Code Online (Sandbox Code Playgroud)

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

list_nonempty([], false).
list_nonempty([_|T], true) :-
    length(T, _).
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

如果length/2没有列表,SWI-Prolog会抛出错误.更加致力于ISO合规性的实现应该失败.使用GNU Prolog:

?- list_nonempty([_|a], true).    
no
Run Code Online (Sandbox Code Playgroud)