1
votes

I want to write a rule in Prolog that returns the even elements in a given list. For example: even_elements([1,2,3,4], Result) would return Result: [2,4]

Here is what I have so far:

% This is my base case.
even_elements([H|T], Result) :- (0 is mod(H,2) -> Result = [H|T] ; Result = T). 

% This is my recursion.
even_elements([H|T], [H|NT]) :- even_elements(T, NT).

The base case works properly and eliminates the first element if it is odd; but the recursion doesn't change anything. Any tips on how to complete the recursion is appreciated.

2
The base case does not look like a base case.Willem Van Onsem

2 Answers

2
votes

Often the base case in list processing deals with the empty list. Indeed, we can just write:

even_elements([], []).

For the recursive case, we can use quite a lot from your base case, the only thin that we still need to do is recurse on the tail of the list, so:

even_elements([H|T], Result) :-
    (  0 is mod(H,2)
    -> Result = [H|T2]
    ;  Result = T2
    ),
    even_elements(T, T2).

That being said, there is no need to implement the logic to filter a list. You can make use of the include/3 predicate [swi-doc], and thus define an even predicate:

even(N) :-
    0 is N mod 2.

Then we can filter with:

even_elements(L, R) :-
    include(even, L, R).

This then gives us:

?- even_elements([1,4,2,5], R).
R = [4, 2].
1
votes

I also found this solution from this post although Willem's answer is way more readable:

even_elements(L1,L2):-findall(X,(member(X,L1), X mod 2=:=0),L2).