Reputation: 49
I have this Prolog code:
f([ ],-1).
f([H|T],S):- f(T,S1), S1>0, !, S is S1+H.
f([_|T],S):- f(T,S1), S is S1.
How can I avoid the second (redundant) recursive call f(T,S1)
, in the third clause, the overall effect of predicate remaining the same?
I know that this could be done by defining an additional predicate.
How can such predicate be defined?
Upvotes: 0
Views: 280
Reputation: 10102
?- length(L,_), f(L,R).
L = [], R = -1
; L = [_A], R = -1
; L = [_A,_B], R = -1
; L = [_A,_B,_C], R = -1
; L = [_A,_B,_C,_D], R = -1
; L = [_A,_B,_C,_D,_E], R = -1
; L = [_A,_B,_C,_D,_E,_F], R = -1
; L = [_A,_B,_C,_D,_E,_F,_G], R = -1
; L = [_A,_B,_C,_D,_E,_F,_G,_H], R = -1
; L = [_A,_B,_C,_D,_E,_F,_G,_H,_I], R = -1
; L = [_A,_B,_C,_D,_E,_F,_G,_H,_I,_J], R = -1
; ... .
Does this ring a bell?
Well, here is what I would respond:
f(L, -1) :-
length(L, _).
Although this now terminates and fails for f(L, 0)
whereas the original definition looped. In case you insist on this equivalence as well:
f(L, MinusOne) :-
length(L, _),
MinusOne = -1.
Upvotes: 1
Reputation: 71075
First we re-write it a little bit to see the similarities better,
f([ ],-1).
f([H|T],S) :- f(T,S1), S1>0, !, S is S1+H.
f([H|T],S) :- f(T,S1), S is S1.
Next we factor out the equal part, and replace its continuation with the new predicate that will do the same thing as was done before, with the same logical variables as were involved there before:
f([ ],-1).
f([H|T],S) :- f(T,S1), additional_predicate(S1,S,H).
Now all that's left to do is to write the same goals under the new name:
additional_predicate(S1,S,H):- S1>0, !, S is S1+H.
additional_predicate(S1,S,H):- S is S1.
And that's that.
Put simply, after the call to f(T,S1)
is done, S1
is already calculated, so there's no need to recalculate it anew.
Upvotes: 0