views:

136

answers:

2

I am new to prolog and I'm trying to to create function that will simply remove all instances of an element from a list. The following code is what I have so far:

remove([H|T], E, L2) :- (\+ ([H|T] == []) ->
    (H == E
        -> remove(T, E, L2)
        ; append(L2, H, L2), remove(T, E, L2)
    )
    ; append(L2, [])
).

When I run this code on:

remove([1,2,3,4,5], 3, L2).

i get an error:

ERROR: Out of global stack

Could someone point me to why I am getting this problem?

+1  A: 

What you need is a SWI's subtract predicate:

 ?- subtract([1,1,2,3,1],[1,2],R).
R = [3].

 ?- listing(subtract).
lists:subtract([], _, []) :- !.
lists:subtract([A|C], B, D) :-
        memberchk(A, B), !,
        subtract(C, B, D).
lists:subtract([A|B], C, [A|D]) :-
        subtract(B, C, D).

true.
Xonix
+3  A: 

This statement

[H|T] == []

can never be true because an empty list can never be identical to a list that contains at least one element.

Kaarel
You are correct. However, in each iteration, I'm passing one less element (the tail), which means that eventually, the list will have no elements and the recursion should stop. At least that the idea...
Adrian
You seem to come from a different background (imperative programming?) and therefore have a fundamental misunderstanding of how Prolog works. I'd recommend you to look at the source code of list processing predicates like member/2, append/3, etc. The basic idea is that lists are immutable, and removing means copying all the wanted elements from one list to another and ignoring the unwanted ones. [H|T]=[] can _never_ be true, even if T = [], then you just have [H]=[] which does not hold.
Kaarel