It's written rather poorly. It might be easier to understand if you refactor it a bit and make it tail recursive:
even_numbers( X , R ) :-
even_numbers( X , [] , T ) ,
reverse( T , R ).
even_numbers( [] , T , T ).
even_numbers( [X|Xs] , T , R ) :-
Z is X mod 2 ,
Z == 0 ,
! ,
even_numbers( Xs , [X|T] , R ).
even_numbers( [_|Xs] , T , R ) :-
even_numbers( Xs , T , R ).
The first predicate, even_numbers/2
predicate is the public wrapper. It invokes the private helper, even_numbers/3
, which hands back the list of even numbers in reverse order. It reverses that and tries to unify it with the result passed in the wrapper.
The helper method does this:
- if the source list is empty: unify the accumulator (T) with the result.
- if the source list is not empty, and the head of the list (X) is even,
- recurse down on the tail of the list (Xs), pushing X onto the accumulator.
- if the source list is not empty, and the head of the list (X) is odd,
- recurse down on the tail of the list (Xs) without modifying the accumulator.
But as noted by @André Paramés, work through it in the debugger and it will become clear what's going on.
[filename].
), start tracing (usingtrace.
) and then calling theeven_number
rule with a list. Seeing its execution step by step is very helpful when trying to understand how it works. – André Paramés