Search code examples
prologprolog-dif

Strange results for list manipulation


I'm trying to implement some predicates for list manipulation in Prolog. Everything works as desired. For example

append([],Ys,Ys).
append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs). 

Sample query:

?- append([1,2,3],[4,5,6],X).
X = [1,2,3,4,5,6].                   % OK

But I'm having trouble with the 'delete'-predicate. Here's how it's implemented:

delete(X,[Y|Ys],Zs) :- X == Y, delete(X,Ys,Zs).
delete(X,[_X|Ys],[_Z|Zs]) :- delete(X,Ys,Zs).
delete(_X,[],[]).

Sample query with bad result:

?- delete(4,[1,2,3,4],X).
X = [_G8975, _G8978, _G8981].       % BAD

I've tested it with further input and it always returns a list of the expected length so in a way it works. But why am I getting only those cryptic _GXXXX and not the numbers?

Many thanks in advance!


Solution

  • One cryptic way to get rid of cryptic variable names is to use numbervars/3, for example,

    ?- length(X, 3).
    X = [_G2019, _G2022, _G2025].
    
    ?- length(X, 3), numbervars(X, 0, _).
    X = [A, B, C].
    

    Now to your delete/3. Apart from other minor problems, like unusual order of the arguments, unusual order of the clauses, etc, you have one major problem: in the second clause, you put a new, anonymous variable where the element of the original list should have been.

    delete(X, [Y|Ys], [Y|Zs]) :- delete(X, Ys, Zs).
    

    With this in the second clause, it sort of works:

    ?- delete(4, [1,2,3,4], L).
    L = [1, 2, 3] .
    
    ?- delete(2, [1,2,3,4,2,3,4], L).
    L = [1, 3, 4, 3, 4] .
    

    There are further problems with your implementation. You can look at the implementation of the same predicate in library(lists) from SWI-Prolog: read the documentation, too!