I was writing few recursive Prolog predicates and ran into a certain point that I don't quite understand at the moment.
For example, I wrote the predicate split/3 that divides a list of integers into a list of non-negative integers and a list of negative integers:
Version 1
split([], [], []).
split([ListHead|ListTail], [ListHead|PList], NList) :-
ListHead >= 0,
split(ListTail, PList, NList).
split([ListHead|ListTail], PList, [ListHead|NList]) :-
ListHead < 0,
split(ListTail, PList, NList).
But before arriving at that solution, I wrote the solution below and wondered for a while why it wasn't working:
Version 2
split([], [], []).
split([ListHead|ListTail], PList, NList) :-
ListHead >= 0,
split(ListTail, [ListHead|PList], NList).
split([ListHead|ListTail], PList, NList) :-
ListHead < 0,
split(ListTail, PList, [ListHead|NList]).
where:
- The first given argument is split into
ListHeadandListTail. - If the
ListHeadelement (integer) is greater than or equal to 0, it's prepended to the list of non-negative integers, and used an argument for the recursive call with an unmanipulatedNlist. - If the
ListHeadelement (integer) is less than 0, it's prepended to the list of negative integers and used as an argument for the recursive call with an unmanipulatedPList.
I'm not getting why version 2 doesn't work; it compiles without any warnings, but only ever returns false. The only difference with the above version is that the prepending of integer elements to Nlist or PList is done within the predicate definition (after the :- operator), and not in the parameters for the predicate call. For me, it makes sense to prepend the result as part of the argument for the next call...
I feel like I'm missing something about Prolog's way of "searching" recursively calls!
Could someone explain why version 1 works as intended whereas version 2 does not?