Recursion 序言:我新创建的列表在退出递归时变为空?

Recursion 序言:我新创建的列表在退出递归时变为空?,recursion,prolog,Recursion,Prolog,我不熟悉prolog,我正处于解决一个问题的边缘,但当我试图退出递归并将列表返回到初始函数时,我遇到了问题。你能帮帮我吗?我一整天都在和它斗争。谢谢 下面是我构建列表后最后发生的情况: 以下是我的谓词: depth_first(N, ReturnList) :- df_real(2:1, N, [2:1], ReturnList). df_real(_:NextRankC, Size, Q, ReturnList) :- genInt(Size, Row), Colum

我不熟悉prolog,我正处于解决一个问题的边缘,但当我试图退出递归并将列表返回到初始函数时,我遇到了问题。你能帮帮我吗?我一整天都在和它斗争。谢谢

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

以下是我的谓词:

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.
调用谓词: 深度_优先(4,Q)。 注意:假设
genInt/2
add/3
list\u-attack/2
工作正常,我的问题是当它最终删除我刚刚构建的所有元素并返回一些变量时,它必须返回列表,而不是true。

使用时更新

 df_real(_:NextRankC, Size, Q, NewList) :-
    ...
    df_real(1:Column, Size, NewList, NewList).
跟踪-添加失败,因为NewList现在是一个列表,而不是要添加到列表中的变量


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

depth_first(N, ReturnList) :-
    df_real(2:1, N, [2:1], ReturnList).
因此,这里第一个查询是以第四个参数作为返回答案列表的变量启动的,
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个参数设置为
ReturnList
是好的,但是在这个子句中目前没有实例化它的调用。因此,您的跟踪显示了其值的
\u XXXX
(它是未实例化的)。问题在于最后一次呼叫:

    df_real(1:Column, Size, NewList, NewList).
出于某种原因,您将
NewList
作为第三个和第四个参数。您可能希望将
ReturnList
作为第四个参数,以便在递归过程中执行该参数,并最终将其设置为:

    df_real(1:Column, Size, NewList, ReturnList).
最后,终端(或基础)情况:

NewList
,因为这里的第四个参数没有任何作用。它是一个单例变量,不包含任何内容。因此,在跟踪中,它将显示为
\u XXXX
,并且您在
返回列表中没有答案。当
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).

您的谓词,
df\u real(uu:NextRankC,Size,Q,u):-…
有一个匿名变量,
(该变量保持未实例化),我假设您希望返回列表。让它成为,
df\u real(\uu:NextRankC,Size,Q,NewList):-…
。此外,为了简洁起见,您的第一个谓词可以写成,
depth\u first(N,ReturnList):-df\u real(2:1,N,[2:1],ReturnList)。
@lower它没有什么区别:(什么没有?把
NewList
作为
df_real
的最后一个参数而不是
?我不明白它怎么会在结果上不起作用。当你把它放在那里的时候,你会得到什么结果?即使它不正确,也一定会有一些不同。从你的部分跟踪来看,它应该会起作用,或者至少会有效果。)u离你想要的要近得多。@Lourger是这样的,它返回TRUE,当我跟踪它时,我得到的输出与检查长度的条件返回TRUE时相同,它从创建的列表中弹出每个元素并返回变量,如图所示:(为了清楚起见,请显示您运行的更新代码和更新的跟踪。如果您按照我的建议进行操作,则跟踪将无法与您在问题陈述中显示的跟踪一样。您遇到的另一个问题是第一个参数也使用了
(在
:NextRankC
术语中).我不确定你打算用那个论点做什么,但它丢失了,因为你把它匿名了。也许没关系,因为你已经在第三个论点中通过了同样的东西。
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).