Greetings,
Trying to delve into de depths of declarative code design and elaborating some notes for teaching my students I stumbled with the following: Solving a very basic excercise “Program a predicate that filters even numeric elements from a list (filter_evens/2)” I started by stating the declarative reasoning that associates the parameters:
(a) An empty list is the even numbers filter of another empty list…
(b) The even numbers filter of a list [X | Rest] is:
(b1) The even numbers filtering of Rest when X is an even number,
(b2) A list [X | R] where R is the even numbers filtering of Rest when X is not an even number.
That reasoning can be translated into the following code:
% filter_evens(<List>, <FilteredList>).
filter_evens([ ], [ ]).
filter_evens([X|Rest], Answer):-
filter_evens(Rest, FilteredRest),
( (number(X), (X mod 2) =:= 0)
*->
Answer = FilteredRest
;
Answer = [X|FilteredRest]
).
Then, testing this code I identified the four obvious “use cases” for the two parameters:
(1) constant-constant, (2)constant-variable, (3) variable-constant, and (4) variable-variable
(I don’t know if that is the correct name for this “phenomenon” but that is as I have called it).
Testing at the console reveals use-cases (1),(2) and (4) work as expected:
?- filter_evens([1,2,3,4,5], [1,3,5]). % Use-case (1)constant-constant...
true.
?- filter_evens([1,2,3,4,5], A). % Use-case (2)constant-variable...
A = [1, 3, 5].
?- filter_evens(List,Answer). % Use-case (4)variable-variable...
List = Answer, Answer = [] ;
List = Answer, Answer = [ _ ] ;
List = Answer, Answer = [ _ , _ ] ;
List = Answer, Answer = [ _ , _ , _ ] .
But that is not the case for use-case (3) that gets stucked:
?- filter_evens(List, [1, 3, 5]).
List = [1, 3, 5] ;
... % here it gets stucked for ever
I first (cinically) assumed that use-case (3) didn’t work just because there was no way, in the code, to logically infere the first argument from the second. But the reality is that I do not fully understand why that happens, nor how to correct it, if it can be corrected at all. Maybe the intitial rationale is not sufficiently declarative. Even use-case (4) is not completely clear to me.
Can anyone help in understanding this, and maybe suggest other course of actions so that, if a use-case doesn’t work, at least it does not gets stuck?
Thanks in advance…