我想在prolog中做一些if | else的事情。下面是我的代码,如果我的输入列表不为空,Prolog将返回'R = 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.发布于 2016-02-18 23:20:01
定义它的一种方法是使用统一(“模式匹配”):
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.但是,如果第一个参数没有落地(也就是说,没有完全实例化),就会发生一些恼人的事情:
?- 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发布于 2017-07-05 20:12:49
我知道这是旧的线程,但是对于那些使用SWI-Prolog的人来说,这仍然是有用的。而不是定义自己的规则,您可以尝试:
nth0(0, List, _).它用于返回列表中的第一个元素,如果列表为空,则返回失败。
发布于 2016-02-18 23:08:13
因为您只处理[H|T]形式的列表,所以您的子句将只匹配至少有一个列表元素的列表。换句话说,您得到空列表的答案false是因为没有匹配的子句,而不是因为长度为0。
https://stackoverflow.com/questions/35484964
复制相似问题