I want to do some if | else stuff in prolog. Below is my code, Prolog will return 'R = false' if my input list is not empty, it will return 'false' if my list is empty. What do I miss?
Code:
isEmpty([H|T],R) :-
length([H|T],L),
( L > 0 -> R = 'false'
;
L =:= 0 -> R = 'true'
).
Prolog Output:
1 ?- isEmpty([],R).
false.
2 ?- isEmpty([1],R).
R = false.
3 ?- isEmpty([1,2,3],R).
R = false.
One way to define this would be to use unification ("pattern matching"):
list_empty([], true).
list_empty([_|_], false).
If you insist on using an if-then-else, you need to pass the list without trying to match it in any way:
list_zerolength(List, Empty) :-
length(List, Len),
( Len == 0
-> Empty = true
; Empty = false
).
... but this is not optimal. The two predicates behave identically if the first argument is indeed a list:
?- list_empty([], R).
R = true.
?- list_empty([_], R).
R = false.
?- list_zerolength([], R).
R = true.
?- list_zerolength([_], R).
R = false.
However, something annoying happens if the first argument is not ground (that is, is not fully instantiated):
?- list_zerolength(L, true).
L = [] ;
ERROR: Out of global stack
So, we try to ask for an empty list, and we get it; however, Prolog insists there might be another answer. When we try to get it, we get an error.
(Extra credit: figure out what happens!)
The predicate list_empty/2
is not perfect, either. Consider:
?- list_empty([_|a], R).
R = false.
This succeeds, and we could interpret the answer as: "The list [_|a]
is not empty". However, this is not ever a proper list!
?- is_list([_|a]).
false.
Using length/2
is not at all a bad idea. We can use it to write a predicate that is arguably a bit more useful than list_empty/2
. I call it list_nonempty/2
to confuse the situation:
list_nonempty([], false).
list_nonempty([_|T], true) :-
length(T, _).
length/2
does a lot more than just finding the length of a list. It can be used to generate lists of increasing length, or check whether its first argument is a proper list:
?- 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)
SWI-Prolog throws an error when length/2
is not given a list. Implementations that are more committed to ISO-compliance should fail instead. With GNU Prolog:
?- list_nonempty([_|a], true).
no
I know it's old thread but still this might be useful for those using SWI-Prolog. Instead of defining their own rules, you can try:
nth0(0, List, _).
It is used to return the first element on the list, which in case of empty list simply fails.
Since you are only dealing with lists of the form [H|T]
your clauses will only match for lists that have at least one list element. In other words, you get the answer false
for the empty list because there is not a matching clause - not because the length is 0.