1

Whenever I run my code, I get an error that the arguments are not instantiated.

ads(X,Z):- mod(X,2) =:= 0, Z is Z+X.
ads(X,Z) :- mod(N,2) =\= 0,Z is Z.

sum_of_nums(0,0,0).
sum_of_nums(X,Y,Z) :-  X=<Y, ad(X,Z), sum_of_nums(X+1,Y,Z).

I want to be able to add numbers from X to Y but only the even ones. Don't know why it doesn't work.

false
  • 10,264
  • 13
  • 101
  • 209
  • The error message will include the line number - don't ignore it. For more advanced debugging: https://www.swi-prolog.org/pldoc/man?section=debugoverview – brebs Feb 25 '22 at 19:11
  • You need to produce a [MCVE](http://stackoverflow.com/help/mcve). – false Feb 25 '22 at 19:31

1 Answers1

2

First, there are some tiny errors, your compiler should indicate, like the unnecessary singleton variables in the second clause. After repairing this, and replacing ads by ad we have:

ad(X,Z):- mod(X,2) =:= 0, Z is Z+X.
ad(X,Z) :- mod(X,2) =\= 0,Z is Z.

sum_of_nums(0,0,0).
sum_of_nums(X,Y,Z) :-  X=<Y, ad(X,Z), sum_of_nums(X+1,Y,Z).

?- sum_of_nums(1,2,S).
   error(instantiation_error,(is)/2).

To locate this error, I will insert some goals false such that the resulting program still produces this instantiation error.

ad(X,Z):- mod(X,2) =:= 0, Z is Z+X, false.
ad(X,Z) :- false, mod(X,2) =\= 0,Z is Z.

sum_of_nums(0,0,0) :- false.
sum_of_nums(X,Y,Z) :-  X=<Y, ad(X,Z), false, sum_of_nums(X+1,Y,Z).

?- sum_of_nums(1,2,S).
   error(instantiation_error,(is)/2).

Therefore, you have an error in this part already.

It's the Z is Z+X. On the right hand side of (is)/2 you always need to have variables that are instantiated (known). And Z is not known.

Variables are a bit different in Prolog. You cannot reassign them.

And also, writing this in Prolog directly doesn't really show what the language is good at.

sum_of(X, Y, 0) :-
   X > Y.
sum_of(X1, Y, Z1) :-
   X1 =< Y,
   ( X1 mod 2 =:= 0 -> S = X1 ; S = 0 ),
   X2 is X1+1,
   sum_of(X2, Y, Z2),
   Z1 is Z2+S.

A more idiomatic way would be:

?- between(1,6,N).
   N = 1
;  N = 2
;  N = 3
;  N = 4
;  N = 5
;  N = 6.
?- between(1,6,N), N mod 2 =:= 0.
   N = 2
;  N = 4
;  N = 6.
?- findall(N, ( between(1,6,N), N mod 2 =:= 0 ), Ns).
   Ns = [2,4,6].
?- findall(N, ( between(1,6,N), N mod 2 =:= 0 ), Ns), sum_list(Ns,Sum).
   Ns = [2,4,6], Sum = 12.

sum_of(X,Y,Sum) :-
   findall(N, ( between(X,Y,N), N mod 2 =:= 0 ), Ns),
   sum_list(Ns,Sum).
false
  • 10,264
  • 13
  • 101
  • 209
  • 1
    Could be a typo in your last definition? `sum_of(X, Y, Z)` doesn't reference Z anywhere. – TessellatingHeckler Feb 27 '22 at 05:11
  • alternatively, `aggregate_all(sum(N), ( between(1,6,N), N mod 2 =:= 0 ), Sum).` or `aggregate_all(sum(N), ( N mod 2 #= 0, between(1,6,N) ), Sum).` to state `N`'s evenness before its range. – Erik Kaplun Mar 11 '22 at 19:52