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/2
、add/3
和 list_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).
我是 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/2
、add/3
和 list_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).