我试图在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) :-
mylength([H1|T1], [T1copy], N1),
N is N1 + 1.
答案 0 :(得分:1)
您的谓词mylength/3
存在以下问题。我认为
您想使用模式mylength(+,-,-)
运行它。就是这样
第一个参数不是降序的情况。
问题是第二个子句,第一个参数[H1|T1]
在头部不变地传递给第一个参数
身体中的谓词,与长度/ 2中发生的情况相反。造成
在无限递归中,因为给定的第二个参数[T1copy]
没有
匹配第一个条款。
无限递归会导致内存耗尽,因为 例如,每次调用都会为H1copy生成一个新变量。 特定的错误消息取决于Prolog系统。
再见
P.S。:可能出现了问题
在咨询谓词时。一个人获得单身警告
H1copy
。
但是例如在最新的SWI-Prolog版本中, 超出本地堆栈错误将需要一些时间,因为 SWI-Prolog可以收集垃圾。在^ C和g之后 我明白了:
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)
我猜以上意味着在当下 在那里我打断了Prolog的翻译 调用堆栈已经深度为552959,即一半 一百万!
运行几分钟后,我得到以下内容
SWI-Prolog中的错误消息:ERROR: Out of local stack
。