I’m using: SWI-Prolog version 8.1.9.
I’m surprised how much trouble I am trying to create what I thought would be a simple predicate. I created the predicate below to take a list of elements, and generate a new list that contains only the elements in the first list that are ground:
The first problem I had was that the usual check for the empty set to terminate a list evaluation, was causing the Tail of the List part of a difference list to unify with the empty set (clause #2), since that is what I was passing to the predicate as the first argument…
To solve that problem I created clause #1 that looks for that condition specifically and ends processing immediately (clause #1). However now I have a new problem and one I can’t seem to escape. The effect of clause #1 is to change a list that has an unground Tail to a list whose last element is a variable.
So:
[cat | Tail]
Becomes
[cat, Tail]
This too kills the List part of a difference list that is passed through the function. Worse, I can’t seem to come up with a way to fix this. I thought I remembered reading about a “not” test that did its work without unifying, but I can’t find it and I don’t know if that would fix things anyways.
How can I shape this predicate so that it does its work without affecting the list passed in as the first argument?
% ----->>>>> select_only_ground_elements(+List, -OnlyGroundElementsList)
% Description: Simple predicate that takes a list and only accepts those
% elements that are ground.
% If the last element is a variable, exit now so we don't
% unify that variable with the empty set.
select_only_ground_elements([LastElement], []) :-
var(LastElement),
!.
% Out of elements and the last element is not a variable. We are done.
select_only_ground_elements([], []) :- !.
select_only_ground_elements([H | T], [H | T_ground]) :-
ground(H),
!,
select_only_ground_elements(T, T_ground).
select_only_ground_elements([_ | T], GroundElements) :-
!,
select_only_ground_elements(T, GroundElements).