You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prolog DCG非直接左递归下无限循环问题及非尾递归修复方案

问题摘要
  • 遇到一种会触发无限循环的Prolog DCG常见模式,代码示例:
s([H|Rest]) --> non_letters, word(H), non_letters, s(Rest).
s([]) --> [].
  • 无法完全确定该无限循环的成因
  • 除转换为尾递归形式外,寻求更优的替代修复方法

详细说明

编写Prolog DCG时多次遇到同类无限循环问题,均为采用递归但未发现直接左递归的相同模式。例如,为实现提取单词、忽略所有非字母字符(类似词法分析器,仅关注有效术语,忽略空格、制表符等),编写了如下代码:

s([H|Rest])    --> non_letters, word(H), non_letters, s(Rest).
s([])          --> [].

non_letters    --> non_letter, non_letters.
non_letters    --> [].

non_letter     --> [C], {\+ code_type(C, alpha)}.

word([L|Rest]) --> letter(L), word(Rest). % ← 注意:word也采用相同模式
word([])       --> [].

letter(C)      --> [C], {code_type(C, alpha)}.

运行查询:

?- phrase(s(Out), `Hello World`).

程序陷入无限循环,无法返回结果。

已知将word改为尾递归形式可修复问题,但无法明确无限递归的确切成因。简化语法后未发现直接左递归,但怀疑当NON_LETTERS和WORD为空时,是否会导致S形成左递归循环:

S           --> NON_LETTERS WORD NON_LETTERS S | ε
NON_LETTERS --> non_letter NON_LETTERS | ε
WORD        --> letter WORD | ε

将word改为尾递归形式后的修复代码:

% ... 其余代码同上,省略 ...

word(Word)           --> letter(L), word_rest([L], Word).

word_rest(Acc, Word) --> letter(L), word_rest([L|Acc], Word).
word_rest(Acc, Out)  --> [], {reverse(Acc, Out)}.

内容的提问来源于Stack Exchange,提问作者Mo...

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 07:20:13