错误:未处理的异常:超出本地堆栈-Prolog
我试图用Prolog编写一个简单版本的错误:未处理的异常:超出本地堆栈-Prolog,prolog,Prolog,我试图用Prolog编写一个简单版本的length/3 如果您看一下length/2的标准实现,它如下所示: length([], 0). length([Head|Tail], N) :- length(Tail, N1), N is 1+N1. 虽然我的代码使用了几乎相同的想法,但我得到了错误“出本地堆栈”,我认为这是因为深层递归。我不明白为什么。我的代码是: mylength(_, [], 0). mylength([H1|T1], [H1copy|T1copy], N)
length/3
如果您看一下length/2的标准实现,它如下所示:
length([], 0).
length([Head|Tail], N) :-
length(Tail, N1),
N is 1+N1.
虽然我的代码使用了几乎相同的想法,但我得到了错误“出本地堆栈”,我认为这是因为深层递归。我不明白为什么。我的代码是:
mylength(_, [], 0).
mylength([H1|T1], [H1copy|T1copy], N) :-
mylength([H1|T1], [T1copy], N1),
N is N1 + 1.
您的谓词mylength/3
有以下问题。我想
您希望以mylength(+、-、-)
模式运行它。然后是
第一个参数不下降的情况
问题是第二个子句,其中第一个参数[H1 | T1]
在head中,未更改地传递给相同的第一个参数
谓词,与length/2中发生的相反。因而发生的
在无限递归中,由于给定的第二个参数[T1copy]
没有
匹配第一个子句
无限递归可能导致内存耗尽,因为
示例每次调用都将为H1copy生成一个新变量。
特定的错误消息取决于Prolog系统
再见
旁白:阿莱迪看到可能有什么不对劲
当查询谓词时。一个人会得到单身警告
对于h1,复制
但例如,在最新的SWI Prolog版本中
本地堆栈外错误将需要一些时间,因为
SWI Prolog不执行carbage收集。在^C和g之后
我明白了:
欢迎使用SWI Prolog(多线程,64位,7.1.16版)
版权所有(C)1990年至2014年阿姆斯特丹大学,阿姆斯特丹
行动(h寻求帮助)?目标
[552959]我的长度([1,2,3],[]],_G40)
[552958]我的长度(“”,,_G40)
[552957]我的长度(“”,,_G40)
[552956]我的长度(“”,,_G40)
[552955]我的长度(“”,,_G40)
我猜上面的意思是目前
在这里,我打断了Prolog解释器
调用堆栈的深度已经达到552959,即一半
一百万
在运行了几分钟后,我得到了以下结果
SWI Prolog中的错误消息:错误:超出本地堆栈
您将T1copy
放入列表中。将[T1copy]
修改为T1copy
。mylength/3
应该准确描述什么?似乎你想要另一个相同长度的列表。这有点复杂:)无论如何:注意你对length/2
的第一个定义不是“标准实现”!对于长度(L,2)
的定义循环!但是它应该只给出一个答案L=[\uu,\u]
。是的,我知道了,谢谢。P.S.:这个例子对于生成堆栈跟踪的prolog系统来说是一个相当大的挑战,因为堆栈跟踪将是巨大的。
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.1.16)
Copyright (c) 1990-2014 University of Amsterdam, VU Amsterdam
Action (h for help) ? goals
[552,959] mylength([1, 2, 3], [[]], _G40)
[552,958] mylength('<garbage_collected>', '<garbage_collected>', _G40)
[552,957] mylength('<garbage_collected>', '<garbage_collected>', _G40)
[552,956] mylength('<garbage_collected>', '<garbage_collected>', _G40)
[552,955] mylength('<garbage_collected>', '<garbage_collected>', _G40)