I am in the following situation: I have a list and I would to delete from it only the last element.
I have implement the following rule (that don't work well):
deleteLastElement([Only],WithoutLast) :-
!,
delete([Only],Only,WithoutLast).
deleteLastElement([_|Tail],WithoutLast) :-
!,
deleteLastElement(Tail,WithoutLast).
The problem is that when I call it, all the element in the list are deleted, in fact if I execute the following statement I obtain:
[debug] ?- deleteLastElement([a,b,c], List).
List = [].
Looking at the trace I think that is clear the cause of this problem:
[trace] ?- deleteLastElement([a,b], List).
Call: (7) deleteLastElement([a, b], _G396) ? creep
Call: (8) deleteLastElement([b], _G396) ? creep
Call: (9) lists:delete([b], b, _G396) ? creep
Exit: (9) lists:delete([b], b, []) ? creep
Exit: (8) deleteLastElement([b], []) ? creep
Exit: (7) deleteLastElement([a, b], []) ? creep
List = [].
When the base case is reached, the WithoutLast list is unified with the empty list [] and when backtracking is performed the WithoutLast still remain the empty list.
This is not good.
I was thinking to implement it doing the following operation:
- Count the number of element in the list before call the predicate that delete the last element.
- Iterate by recursion and decrement the value of the number of element each time
- If it is true that the number of element is 0 it means that this is the last element so I delete it from the original list
But this seems to me not clear and not so good, I would know if there is a declarative good solution for this problem.