Here is a list length method:
list_length([], 0).
list_length([_|T], N) :- list_length(T, TN), N is TN + 1.
If I query list_length(X, 1) and pass over the first answer, it infinite loops. Here's a trace:
| ?- list_length(X, 1).
1 1 Call: list_length(_26,1) ?
2 2 Call: list_length(_58,_97) ?
2 2 Exit: list_length([],0) ?
3 2 Call: 1 is 0+1 ?
3 2 Exit: 1 is 0+1 ?
1 1 Exit: list_length([_57],1) ?
X = [_] ? ;
1 1 Redo: list_length([_57],1) ?
2 2 Redo: list_length([],0) ?
3 3 Call: list_length(_84,_123) ?
3 3 Exit: list_length([],0) ?
4 3 Call: _151 is 0+1 ?
4 3 Exit: 1 is 0+1 ?
2 2 Exit: list_length([_83],1) ?
5 2 Call: 1 is 1+1 ?
5 2 Fail: 1 is 1+1 ?
2 2 Redo: list_length([_83],1) ?
3 3 Redo: list_length([],0) ?
4 4 Call: list_length(_110,_149) ?
4 4 Exit: list_length([],0) ?
5 4 Call: _177 is 0+1 ?
5 4 Exit: 1 is 0+1 ?
3 3 Exit: list_length([_109],1) ?
6 3 Call: _206 is 1+1 ?
6 3 Exit: 2 is 1+1 ?
2 2 Exit: list_length([_83,_109],2) ?
I don't quite understand what's happening in the trace, especially after X = [_] ? ;.
I do understand why list_length([],0) :- ! fixes the problem.
I'm in the process of learning Prolog and logic programming so would like to more deeply understand what's going on here and why this infinite loop is happening. I understand the execution model and order at a basic level.