该函数尾部递归吗?为什么大型列表失败?

时间:2019-07-08 10:13:51

标签: prolog tail-recursion

此函数尾部递归吗?

incNth(0, [H1|T], [H2|T]) :-
  H2 is H1 + 1.
incNth(N, [H|T1], [H|T2]) :-
  N > 0, N2 is N - 1,
  incNth(N2, T1, T2).

对于包含500,000个元素的列表,prolog表示它用完了堆栈内存。我该如何解决?

编辑:我正在尝试使用此功能代替此功能

insert(Ind,List,Val,NList) :-
    nth0(Ind,List,_,R),
    nth0(Ind,NList,Val,R)

1 个答案:

答案 0 :(得分:0)

我无法重现您的问题。使用SWI-Prolog,并且堆栈限制为1GB,我可以列出1万个元素(即1e7),并成功将谓词应用于该列表。

?- N = 10 000 000, length(L, N), maplist(=(0), L), incNth(N-1, L, R).
N = 10000000,
L = [0, 0, 0, 0, 0, 0, 0, 0, 0|...],
R = [0, 0, 0, 0, 0, 0, 0, 0, 0|...] ;
false.

此列表比您的列表长2 * 10倍。

如果我尝试列出更长的列表,则这是我用尽堆栈空间的时候。已经抛出:

?- N = 50 000 000, length(L, N).
ERROR: Stack limit (1.0Gb) exceeded
ERROR:   Stack sizes: local: 1Kb, global: 4Kb, trail: 2Kb
ERROR:   Stack depth: 11, last-call: 18%, Choice points: 3
ERROR:   In:
ERROR:     [11] system:'$length'(_1226, 50000000)
ERROR:     [9] system:'<meta-call>'(<compound (:)/2>)
ERROR:     [8] '$tabling':'$wfs_call'(<compound (:)/2>, <compound (:)/2>)
ERROR:     [7] '$toplevel':toplevel_call(<compound (:)/2>, <compound (:)/2>)
ERROR:     [5] '$toplevel':'$execute_goal2'(<compound (:)/2>, [length:3])
ERROR: 
ERROR: Use the --stack_limit=size[KMG] command line option or
ERROR: ?- set_prolog_flag(stack_limit, 2_147_483_648). to double the limit.

请说明如何运行该程序以及看到的错误。还要告诉我们您正在使用什么Prolog实现。