Prolog:递归无法正常工作

Posted

技术标签:

【中文标题】Prolog:递归无法正常工作【英文标题】:Prolog: recursion is not working properly 【发布时间】:2022-01-19 12:31:37 【问题描述】:

我想写change_state(+L1, +L2, -L3).

L1 包含状态,例如:[碾磨、烧毁] L2 包含谓词,例如:[del(milled), add(shifted)] 而L3就是返回列表。

例子:

L1 = [milled, burned]
L2 = [del(burned), add(shifted)]
L3 = [milled, shifted]

所以 L1 是我的起始列表,根据 L2 中的谓词,我会更改 L1 的状态。

这是我的递归解决方案:

change_state([], [], []).

change_state(X, [], []).

change_state(State, [H|T], NewState) :-
    functor(H, N, 1),
    arg(1, H, A),
    (    N = del 
    ->   remove_from_list(A, State, NewState)
    ;    arg(1, H, A),
         add_to_list(A, State, NewState) ),
    print(NewState),
    change_state(NewState, T, X),
    print(NewState).

我还把一些打印到函数中进行调试。

现在的问题:

如果我用

调用函数
change_state([milled, burned], [del(burned), add(lol), add(hi)], L).

我得到了结果

L = [milled].

所以只有 L2 中的第一个谓词有效。

但打印显示我:

[milled][lol,milled][hi,lol,milled][hi,lol,milled][lol,milled][milled].

所以它确实有效,但是由于递归,它回到了第一个状态。

知道如何解决这个问题吗?

【问题讨论】:

change_state(State, [H|T], NewState) :- ... 不应该是change_state(State, [H|T], X) :- ... 考虑到您的几乎尾递归调用change_state(NewState, T, X) @RuudHelderman 刚刚尝试过,但现在我的退货清单是空的。 子句 change_state(X, [], []). 必须替换为 change_state(X, [], X) 结合你的两个答案有效!非常感谢!! 【参考方案1】:

虽然您的代码已经在 cmets 中指示的修改下正常工作,但我认为更清晰的实现如下:

change_state(State, Changes, NewState) :-
    change_state_loop(Changes, State, NewState).

% Reverse the order of the first two arguments to avoid choice points.

change_state_loop([], State, State).
change_state_loop([Change|Changes], State, NewState) :-
    do(Change, State, PartiallyUpdatedState),
    change_state_loop(Changes, PartiallyUpdatedState, NewState).

% Use unification to choose the correct operation to perform.

do(del(Fluent), State, NewState) :- subtract(State, [Fluent], NewState).
do(add(Fluent), State, NewState) :- union(State, [Fluent], NewState).

【讨论】:

或者在foldl存在的情况下,change_state(State, Changes, NewState) :- foldl(do, Changes, State, NewState). @RuudHelderman 不错!我真的很喜欢基于foldl/4 的解决方案。但是,我认为使用foldl/4 可以使代码更简洁,但不一定更清晰(当然对于初学者而言)。

以上是关于Prolog:递归无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

Prolog递归永远循环

我使用 dislousreGroup 作为递归,但视图更新无法正常工作。有啥办法吗?

Prolog中两个执行偶数和奇数的区别

如何使用有限谓词递归确定序言中的商?

Prolog解析证明器删除括号

Prolog中的广度优先搜索