在使用DCG反转字符串时,Prolog如何判断何时结束递归?

编程语言 2026-07-12

我正在使用Scryer Prolog。我从Power of Prolog的 YouTube频道看到这个:

qes([]) --> [].
qes([L|Ls]) --> qes(Ls), [L].

使用listing,我得到了它在Prolog子句中的形式:

?- listing(qes/3).
qes([],A,B) :-
   A=B.
qes([L|Ls],A,B) :-
   qes(Ls,A,C),
   C=[A|B].
   true.

我正在努力逐步弄清它的执行过程。
当我调用phrase(qes, "abc").时,它在内部被转换为qes(X, "abc",[]).

它们被统一:X = [L|Ls], A = "abc", B = []. Prolog尝试基条款。abc不等于 []。

第一次调用:

qes([L1|Ls1], "abc", []) :- qes(Ls1,"abc",C1), C1=[L1|[]].

第二次调用:

qes([L2|Ls2], "abc", C2) :- qes(Ls2,"abc",C2), C2=[L2|C1].

类似地,第三次调用也是如此。由于L 与Ls是变量,在基准情形成功之前它们都不会被绑定到任何东西,那么Prolog如何知道何时结束递归?在我看来,没有任何情形是任何Ls = []。Prolog如何进入基准情形?

解决方案

我使用了SWI-Prolog,但在Scryer上也应该可以完全做到同样的效果。我加载了你的代码,测试它确实能工作,然后对谓词进行了 跟踪,以按顺序查看发生了什么:

102 ?- phrase(qes(`abc`), S).
S = [99, 98, 97].

103 ?- trace(qes//1).
%     qes/3: [all]
true.

104 ?- phrase(qes(`abc`), S).
 T [15] Call: qes([97, 98, 99], _30682, [])
 T [22] Call: qes([98, 99], _30682, _32214)
 T [29] Call: qes([99], _30682, _33258)
 T [36] Call: qes([], _30682, _34302)
 T [36 +0.2ms] Exit: qes([], _30682, _30682) % second and third argument
                                             % are now the same!
 T [29 +0.9ms] Exit: qes([99], [99|_33258], _33258)
 T [22 +1.3ms] Exit: qes([98, 99], [99, 98|_32214], _32214)
 T [15 +1.9ms] Exit: qes([97, 98, 99], [99, 98, 97], [])
S = [99, 98, 97].

你现在看清楚了吗?

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章