Streamline
Streamline

Reputation: 63

Uninstantiated variable at end of list in SWI-Prolog

I wrote a program to sort numbers from symbols, and it works, but gives me a memory address at the end of the list that it didn't run through last. Why is that so?

separate([],[],[]).
separate([X],X,_):-number(X).
separate([X],_,X).
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
separate([X|Y],Z,[X|S]):-separate(Y,Z,S).

When consulting with ?- separate([3,a,b,4,5,c],X,Y).

I get:

X = [3, 4, 5|_G2592],
Y = [a, b, c] .

Upvotes: 1

Views: 1180

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477666

That's because you leave your list tails open:

separate([X],X,_):-number(X).
separate([X],_,X).

The thing is: you actually do not need to write these statements, you could have omitted them:

separate([],[],[]).
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
separate([X|Y],Z,[X|S]):-separate(Y,Z,S).

This would have worked but it would return multiple results, and except the first, all the remaining are wrong. You should solve this by adding a guard to the last clause:

separate([],[],[]).
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
separate([X|Y],Z,[X|S]):-\+ number(X),separate(Y,Z,S).

Where \+ acts like a "not" in the sense that \+ number(X) will succeed if Prolog cannot match number(X).

A final note is that what you see is not really a memory address: it is simply an uninstantiated variable, although that is of course a minor remark.

Upvotes: 1

max66
max66

Reputation: 66230

I propose

separate([],[],[]).

separate([H | T], [H | Tn], Ls) :-
  number(H),
  separate(T, Tn, Ls).

separate([H | T], Ln, [H | Ts]) :-
  \+ number(H),
  separate(T, Ln, Ts).

If you have a terminal clause as separate([],[],[]) and a couple of ordinary clauses as separate([X|Y],[X|Z],S) and separate([X|Y],Z,[X|S]), you don't need semi-terminal clauses as separate([X],X,_) and separate([X],_,X) and they (with the undefined value _) avoid the unification of one of the lists and you get the "memory address" (the identifier of a not-unified variable).

And if you have a clause with number(X), the other (alternative) clause need the "not-number" check (that is \+ number(X)) otherwise both clauses are true with numbers and you multiply solutions, with numbers in the list of not numbers.

Upvotes: 2

Related Questions