我想做一些如果|在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.
答案 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。