简体   繁体   English

将尾递归prolog代码改写为简单递归

[英]Rewriting tail recursion prolog code into simple recursion

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.我是 prolog 的新手,我想练习将尾递归代码重写为简单的递归以更好地理解该过程,但我没有成功。 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.注意:在 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:您的程序在 Prolog 中使用“列表迭代”的常见模式(欢迎使用更好的名称进行评论),这与使用累加器的递归相反:

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.最简单有趣的情况可能是反转一个列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM