views:

172

answers:

2

I'm writing a predicate to add two vectors. This is what I came up with:

add( [], [], 0 ).
add( [A], 0, A ).
add( [A], [B], C ) :- C is A + B.
add( A, B, C ) :- add( B, A, C ).
add( [H1|T1], [H2|T2], WYNIK ) :- X is H1 + H2, add( T1, T2, Y ), append( [X], Y, WYNIK ).

First four lines work just fine, but I can't get the last one to work - what do I do wrong?

+2  A: 

In this order, the last line will never be run. The line:

add( A, B, C ) :- add( B, A, C ).

will unify with anything that hasn't already been handled by a rule above it.

Jeff Dallien
+1  A: 

As Jeff observed, the problem is the rule:

add( A, B, C ) :- add( B, A, C ).

In general, this is a rule that expresses something that you want to be true, but that doesn't help you solve a goal. The query add(1,2,X) by this rule leads to the subquery add(2,1,X), which leads to the subquery add(1,2,X): SLD resoltuion can spend forever on this branch (if it has no other rules of higher priority, and it doesn't spot that the rule doesn't make progress) without getting anywhere. You should only use such rule with conditions (e.g. strictlylessthan (B,A)) that ensure the rule is only applicable when it can do useful work. The issue of these kinds of rules is a reason why Prolog is not really a declarative language.

To regain commutativity, you'll need to add the rul:

add (0, [A], A).

Your add predicate is kind of odd: add([1],0,1) is true, as is add([1],[0],1), but add([0],1,1) is not, nor is add([1],[0],[1]). add is perfectly meaningful from a computational point of view, but is it really what you want?

Charles Stewart