1
votes

I'm learning swi Prolog and I wanted to create predicate that adds +2 for each element.

So I wrote something like this:

addUp([],_).
addUp([H|T],R):-addUp(T,R),is_list(R)->append([H+2],R,R);R=[H+2|[]].

addUp([1,2],X).

But it always returns false. Why?

2

2 Answers

2
votes

First an advice: learn to use maplist/3: with that you will write

addUp(Xs, Ys) :- maplist(addUp2, Xs, Ys).
addUp2(X, Y) :- Y is X + 2.

or better, a more reusable snippet...

addUp(Xs, Ys) :- maplist(addUp(2), Xs, Ys).
addUp(N, X, Y) :- Y is X + N.

Anyway, arithmetic in Prolog must be evaluated 'explicitly', and your code must be simplified a lot to work

addUp([], []).
addUp([H|T], [H1|T1]) :- H1 is H+2, addUp(T, T1).
1
votes

But it always returns false. Why?

Your definition does not always fail:

?- addUp([1],X).
X = [1+2].

So sometimes it succeeds. And it seems that this case is more or less what you wanted. Where else does it succeed? In other programming languages you would have to guess or, heaven forbid, read the program. In Prolog, there is no need for this. Simply find a good query. A good candidate is the most general query:

?- addUp(Xs,Ys).
Xs = [] ...

So your definition succeeds for Xs equal to [], and Ys equal to ... well, equal to anything. Therefore, this answer is too general.

Another goal catches my eye: is_list(R)->append([H+2],R,R). Let's imagine, when this will be true. For R = [] not, nor for R = [_]. In fact, there is no length, where this will be true.

Now, we can start fixing your program. See chac/CapelliC's suggestion.