I'm quite new in prolog and I want to practice rewriting a tail-recursion code into a simple recursion to understand better the process, but I did not succeed in it. If anybody can help with it I would really appreciate it.
Note: Converting tail-recursive (tail-call) code to non tail-recursive code is not a wise thing to normally do in Prolog. This question is only for academic purposes of learning.
The code:
some_predicate(T,1,3,0,D),
%the tail has elements with ID and Numbers like [(1,3),(2,5),(4,3)])
%in the D I count steps if different conditions are fulfilled
%I would like to write something like: some_predicate(T,1,3,D) without the Acc
some_predicate(_, _, 1, D, D):-!.
some_predicate([], _, _, D, D):-!.
some_predicate([(UP,_)|_], ID, H, D, D):-
UP >= ID + H,
!.
some_predicate([(UP,UH)|T], _, H, D, RetD):-
H > UH,
TH is H - 1,
TD is D + 1,
some_predicate(T, UP, TH, TD, RetD),
!.
some_predicate([(UP,UH)|T], _, _,D, RetD):-
TD is D + 1,
some_predicate(T, UP, UH, TD, RetD),
!.
My attempt
some_predicate(_, _, 1,0):-!.
some_predicate([], _, _,0):-!.
some_predicate([(UP,_)|_], ID, H, 0):-
UP >= ID + H,
!.
some_predicate([(UP,UH)|Er], _, H, D):-
H > UH,
some_predicate(Er, UP, TH, TD),
H is TH - 1,
D is TD + 1,
!.
some_predicate([(UP,UH)|Er], _, _,D):-
some_predicate(Er, UP, UH, TD),
D is TD + 1,
!.
A comment in the question says that you would like to rewrite the code without an accumulator, but it doesn't use an accumulator. The general schema for predicates using a list accumulator would be something like this:
foo(X, Ys) :-
foo(X, [], Ys).
foo(X, Acc, Acc) :-
bar(X).
foo(X, Acc, Ys) :-
baz(X, Y, Z),
foo(Z, [Y | Acc], Ys).
The recursive call involving the list accumulator gets a bigger list than the accumulator was before. You add something to the accumulator before you pass it to the recursive call.
Your program instead uses the common pattern of "list iteration" (comments with a better name are welcome) in Prolog which does the opposite of recursion using an accumulator:
foo([], Y) :-
bar(Y).
foo([X | Xs], Y) :-
baz(X),
foo(Xs, Y).
(This uses similar names to the predicate before, but I'm not saying that they are equivalent.)
The list constructor [_ | _]
is in the head of the clause, not in a recursive call. The list in the recursive call is smaller than the list in the head. You remove something from the list before you pass the tail to the recursive call.
This is therefore not an answer your question, just a hint that you need to start from the right place: Some predicate definition that really does use an accumulator list. The simplest interesting case is probably reversing a list.