首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >判断列表是否为空

判断列表是否为空
EN

Stack Overflow用户
提问于 2016-02-18 23:01:16
回答 3查看 15.6K关注 0票数 2

我想在prolog中做一些if | else的事情。下面是我的代码,如果我的输入列表不为空,Prolog将返回'R = false‘,如果我的列表为空,它将返回'false’。我错过了什么?

代码:

代码语言:javascript
运行
复制
isEmpty([H|T],R) :- 
    length([H|T],L),
    ( L > 0 -> R = 'false'
    ;
    L =:= 0 -> R = 'true'
    ).

Prolog输出:

代码语言:javascript
运行
复制
1 ?- isEmpty([],R).
false.

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

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

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-18 23:20:01

定义它的一种方法是使用统一(“模式匹配”):

代码语言:javascript
运行
复制
list_empty([], true).
list_empty([_|_], false).

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

代码语言:javascript
运行
复制
list_zerolength(List, Empty) :-
    length(List, Len),
    (   Len == 0
    ->  Empty = true
    ;   Empty = false
    ).

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

代码语言:javascript
运行
复制
?- list_empty([], R).
R = true.

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

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

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

但是,如果第一个参数没有落地(也就是说,没有完全实例化),就会发生一些恼人的事情:

代码语言:javascript
运行
复制
?- list_zerolength(L, true).
L = [] ;
ERROR: Out of global stack

因此,我们试图请求一个空列表,我们得到了它;然而,Prolog坚持认为可能会有另一个答案。当我们试图获取它时,我们得到了一个错误。

(额外的奖励:弄清楚会发生什么!)

谓词list_empty/2也不是完美的。考虑一下:

代码语言:javascript
运行
复制
?- list_empty([_|a], R).
R = false.

这成功了,我们可以将答案解释为:“列表[_|a]不为空”。然而,这永远不是一个proper list

代码语言:javascript
运行
复制
?- is_list([_|a]).
false.

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

代码语言:javascript
运行
复制
list_nonempty([], false).
list_nonempty([_|T], true) :-
    length(T, _).

length/2所做的远不止是查找列表的长度。它可以用来生成递增长度的列表,或者检查它的第一个参数是否是正确的列表:

代码语言:javascript
运行
复制
?- 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:

代码语言:javascript
运行
复制
?- list_nonempty([_|a], true).    
no
票数 6
EN

Stack Overflow用户

发布于 2017-07-05 20:12:49

我知道这是旧的线程,但是对于那些使用SWI-Prolog的人来说,这仍然是有用的。而不是定义自己的规则,您可以尝试:

代码语言:javascript
运行
复制
nth0(0, List, _).

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

票数 4
EN

Stack Overflow用户

发布于 2016-02-18 23:08:13

因为您只处理[H|T]形式的列表,所以您的子句将只匹配至少有一个列表元素的列表。换句话说,您得到空列表的答案false是因为没有匹配的子句,而不是因为长度为0。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35484964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档