Jack
Jack

Reputation: 7

Prolog if then else logic (error: operator priority clash)

I'm new to prolog and doing so practice to pick it up. I'm confused at the moment with an error on line 5 saying Syntax error: Operator priority clash. This is probably due to the nesting of the logic, but I was wondering if there is a way to make this nesting work.

loopOver3(elt1, elt3, [H|T], sum):-
    ( =(elt1, elt2) =:= true ->  
      sum is sum + (elt1 + elt2),
      ;   =(elt1, elt2) =\= false -> ( =(elt1, H) =:= true ->  
            sum is sum + (elt1 * H),
            ;  =(elt1, H) =\= false -> ( =(elt2, H) =:= true ->  
                    ( \=(H, 0) =:= true ->
                      sum is sum + (100 / H)
                    )
                )
          )
    )
    loopOver3(elt1, elt3, T, sum).

Sudo code for what I'm trying to do:

for elt3 in list3: 
    if elt1 == elt2: 
        sum = sum + (elt1 + elt2) 
    else: 
        if elt1 == elt3: 
            sum = sum + (elt1 * elt3) 
        else: 
            if (elt2 == elt3) and (elt3 != 0): 
                sum = sum + (100 / elt3)

Upvotes: 0

Views: 239

Answers (1)

Enigmativity
Enigmativity

Reputation: 117064

You have a bit of work to go to understand the concepts in Prolog. Your initial attempt is full of atoms (lowercase) rather than variables (uppercase). It's got mutability. You're thinking like Prolog has functions (it has predicates) that return values (they don't - they either succeed or fail).

I've made the assumption that you're peeling the first three values off of a list and then dropping the first item and recursing down.

So, if I have this list [1,2,1,2], I'd first be looking at [1,2,1] and then [2,1,2].

Or, in this longer example:

[1,2,1,2,2,1,1] => [1,2,1]
[2,1,2,2,1,1] => [2,1,2]
[1,2,2,1,1] => [1,2,2]
[2,2,1,1] => [2,2,1]
[2,1,1] => [2,1,1]

As soon as the list has only 2 elements I can then stop.

I'm assuming that each of the list of three values are your [Elt1, Elt2, Elt3].

To compute this we need to have an input list and an output sum, but to recurse down the list we need to have an accumulator to keep track of the current sum as we go. The first predicate is easy:

compute(List,Sum) :- compute(List,0,Sum).

Now, you have 5 predicates that we must match for.

  1. the list containing 2 elements - we can return our accumulator
  2. Elt1 = Elt2 then sum = sum + (elt1 + elt2)
  3. Elt1 = Elt3 then sum = sum + (elt1 * elt3)
  4. Elt2 = Elt3 and Elt3 \= 0 then sum = sum + (100 / elt3)
  5. None of the above so we just pass along the current accumulator, i.e. sum = sum
compute([_,_],Sum,Sum).

compute([Elt1,Elt2,Elt3|Tail],AccNow,Sum) :-
    Elt1 = Elt2,
    !,
    AccNext is AccNow + Elt1 + Elt2,
    compute([Elt2,Elt3|Tail],AccNext,Sum).

compute([Elt1,Elt2,Elt3|Tail],AccNow,Sum) :-
    Elt1 = Elt3,
    !,
    AccNext is AccNow + Elt1 * Elt3,
    compute([Elt2,Elt3|Tail],AccNext,Sum).

compute([_,Elt2,Elt3|Tail],AccNow,Sum) :-
    Elt3 \= 0,
    Elt2 = Elt3,
    !,
    AccNext is AccNow + 100 / Elt3,
    compute([Elt2,Elt3|Tail],AccNext,Sum).

compute([_,Elt2,Elt3|Tail],Acc,Sum) :-
    compute([Elt2,Elt3|Tail],Acc,Sum).  

If I try this on ?- compute([1,2,1,2],X). then I get X = 5. That's matching on the Elt1 = Elt3 predicate and giving me 0 + 1 * 1 and then again on the Elt1 = Elt3 predicate giving me 1 + 2 * 2 or 5.

If I try this on ?- compute([1,2,1,2,2,1,1],X). then I get X = 159. I'll leave it to you to see that it is the right result.

Just keep in mind that all Prolog is trying to do is succeed. If asked to prove a goal (i.e. compute/3) it finds the first predicate that matches and tries to prove that (by proving any subgoals) and when it fails it just backtracks to the previous choice point and tries another choice and to continue. If it proves the original goal then it succeed. If it didn't then it failed. There are no return values - only bound variables.

Upvotes: 1

Related Questions