Prolog:我新创建的列表在退出递归时变空了吗?

Prolog: My newly created list becomes empty on exiting recursion?

我是 prolog 的新手,我正处于解决一个问题的边缘,但是当我尝试退出递归并 return 将列表返回到初始函数时我遇到了问题。你能帮帮我吗?我整天都在为此苦苦挣扎。谢谢

以下是我构建列表后最终发生的情况:

这是我的谓词:

depth_first(N, ReturnList) :-
   df_real(2:1, N, [2:1], ReturnList).

df_real(_:NextRankC, Size, Q, ReturnList) :- 
   genInt(Size, Row), 
   Column is NextRankC + 1,
   Rank = Row:Column,
   not(list_attack(Rank, Q)),
   add(Rank, Q, NewList),
   df_real(1:Column, Size, NewList, NewList).
% Recursive Case: Exit when list is full.
df_real(_, N, Q, Newlist) :- length(Q, Length),
   N = Length.

调用谓词: depth_first(4,Q)。 注意:假设 genInt/2add/3list_attack/2 工作正常,我的问题是最后它只是删除了我刚刚构建的所有元素并且 returns 一些变量,而不是 true,它必须 return 列表。

更新当我使用

 df_real(_:NextRankC, Size, Q, NewList) :-
    ...
    df_real(1:Column, Size, NewList, NewList).

跟踪 - 添加失败,因为 NewList 现在是列表而不是要添加到列表的变量。

最终,代码的问题是您需要为 returning 列表设置适当的模式。 Prolog 中的一个常见模式是传入一个变量参数,该参数贯穿所有递归并最终在终端案例中实例化。该变量最初在第一个子句中设置。

depth_first(N, ReturnList) :-
    df_real(2:1, N, [2:1], ReturnList).

所以这里第一个查询是用第 4 个参数作为 return 答案列表 ReturnList 的变量启动的。到目前为止,还不错。

df_real(_:NextRankC, Size, Q, ReturnList) :- 
    genInt(Size, Row), 
    Column is NextRankC + 1,
    Rank = Row:Column,
    not(list_attack(Rank, Q)),
    add(Rank, Q, NewList),
    df_real(1:Column, Size, NewList, NewList).

最初,您将 _ 作为第 4 个参数,这是不正确的,因为您 需要 第 4 个参数作为变量,您可以 return答案。现在将第 4 个参数设置为 ReturnList 很好,但是此子句中当前没有调用来实例化它。因此,您的跟踪显示 _XXXX 的值(未实例化)。问题出在最后一次调用:

    df_real(1:Column, Size, NewList, NewList).

出于某种原因,您将 NewList 作为第 3 个和第 4 个参数。您可能希望 ReturnList 作为第 4 个参数,以便它通过递归进行并最终被设置:

    df_real(1:Column, Size, NewList, ReturnList).

最后,终端(或基本)案例:

% Recursive Case: Exit when list is full.
df_real(_, N, Q, Newlist) :-
    length(Q, Length),
    N = Length.

NewList 因为这里的第四个参数什么都不做。它是一个单例变量,不会填充任何内容。所以在跟踪中,它会显示为 _XXXX 而你将在 ReturnList 中没有答案。当 Q 列表达到长度 N 时,该子句表示您已完成。我想,到那时,Q 就是您想要的答案。所以你只需要这样说,在序言中:

% Recursive Case: When list is full, it's the answer
df_real(_, N, Q, Q) :-
    length(Q, N).

您还可以通过简化第一个参数来稍微整理一下。这是一个 X:Y 形式的术语,而您从不使用 X,所以为什么要随身携带它?

depth_first(N, ReturnList) :-
    df_real(1, N, [2:1], ReturnList).

df_real(_:NextRankC, Size, Q, ReturnList) :- 
    genInt(Size, Row), 
    Column is NextRankC + 1,
    Rank = Row:Column,
    \+ list_attack(Rank, Q),   % Note use of ISO negation predicate, \+
    add(Rank, Q, NewList),
    df_real(Column, Size, NewList, ReturnList).

% Recursive Case: When list is full, it's the answer
df_real(_, N, Q, Q) :-
    length(Q, N).