1

I'm trying to write a recursive function in prolog that computes R = (2*X + Y)^N without using the exponent operator. I've written a recursive function with if-else statements and I get the error: ) or operator expected. It looks to me like I have the syntax correct, but I must be missing something. The code is below.

expbar(R, X, Y, N) :-
    (X =:= Y =:= N =:= 0 -> 
        write("No two variables can equal 0 at the same time.");
        (N =:= 0 ->
            R is 2 * X + Y;
            R is (2 * X + Y) * expbar(R, X, Y, N-1)
        )
    ).
Mat
  • 202,337
  • 40
  • 393
  • 406
aclark
  • 219
  • 1
  • 4
  • 13

3 Answers3

2

You are using the expression 2*X+Y all the time. Why not calculate it first and then use that result for the actual computation? Maybe you missed here something in the problem statement?

Why do you want to exclude the case where X, Y and N are all 0? ... while you are not excluding the case of N < 0?

Argument order

It is common in Prolog to put results after the corresponding input arguments. There are exceptions to this rule, (is)/2 is the most common example, but it is written as an infix operator.

Error signalling

For cases you cannot handle properly there are two options in Prolog. Either you silently fail or you issue a clean error. (There is a third – looping, which while not ideal is still better than succeeding.) Currently, you write out a text and then you succeed. So you are assuming that someone will read your message. But frequently programs run unattended and the message is ignored.

Imagine I want to use your definition to prove that your definition is the question to the answer:

?- expbar(42, 0, 0, 0).

This is what I get in SWI after rewriting X =:= Y =:= N =:= 0 to X =:= 0, Y =:= 0, N =:= 0.

?- expbar(42, 0, 0, 0).
[78,111,32,116,119,111,32,118,97,114,105,97,98,108,101,115,32,99,97,110,32,101,113,117,97,108,32,48,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46]
true.

It says true.! And these numbers above are certainly some progress messages from such a highly complex calculation... So it is very easy to misread your message. It would have been a bit easier if you would have used single quotes. More about single and double quotes. But even with a more readable message, it is easy to skip it.

The proper way to handle such a situation is by issuing an error:

    throw(error(Error_term,_More_info))

In this manner the computation is aborted and the error is handled by the toplevel (or the next place where a catch/3 handles it). This lowers the chances that the error will be misinterpreted.

The Error_term should be ideally one of the existing error terms. Here is the complete list of errors in ISO Prolog. In your case it might an evaluation_error(undefined) similarly to the definition of exponentiation.

Community
  • 1
  • 1
false
  • 10,264
  • 13
  • 101
  • 209
0

expbar is not a function. Correct is

expbar(R, X, Y, N) :-
(X =:= Y =:= N =:= 0 -> 
    write("No two variables can equal 0 at the same time.");
    (N =:= 0 ->
        R is 2 * X + Y;
        N1 is N - 1,
        expbar(R1, X, Y, N1)
        R is (2 * X + Y) * R1
    )
).
joel76
  • 5,565
  • 1
  • 18
  • 22
  • I implemented this code but am still getting the ") or operator expected" What is this and how do I fix it? – aclark Apr 23 '12 at 02:39
  • @aclark, please look at the other answers `X =:= Y =:= N =:= 0` is invalid syntax – false Apr 23 '12 at 15:02
0

You should have a syntax error on initial condition. Adding to joel76 answer:

expbar(R, X, Y, N) :-
    (   ( X =:= 0, Y =:= 0 ; X =:= 0, N =:= 0 ; Y =:= 0, N =:= 0 )
    ->  write("No two variables can equal 0 at the same time.")
    ;   (   N =:= 0
        ->  R is 2 * X + Y
        ;   N1 is N - 1,
            expbar(R1, X, Y, N1),
            R is (2 * X + Y) * R1
        )
    ).
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • the value of `R` if `N =:= 0` would be `1` more than `2 * X + Y` I think. And the expression is calculable as long as `2 * X + Y` or N is different of `0`, the test cases might be too broad. – m09 Apr 22 '12 at 13:19