如何在 Prolog 中断言 DCG 规则?

How do I assert a DCG rule in Prolog?

以下 Prolog 为目标 test1test2 打印 done,但不打印 test3。我的理解是这段代码中的 match_test2match_test3 应该是等价的。如何通过断言创建 DCG 规则?

setup(['t','e','s','t']).

match_test1 --> ['t','e','s','t'].
test1 :-
    setup(C),
    phrase(match_test1,C),
    write("done").

test2 :-
    setup(C),
    assert(match_test2(['t','e','s','t'],[])),
    phrase(match_test2,C),
    write("done").

test3 :-
    setup(C),
    assert(match_test3 --> ['t','e','s','t']),
    phrase(match_test3,C),
    write("done").

将 SWI-Prolog 版本 7.2.3 用于 x86_64-darwin14.3.0,运行 作为 swipl -l bug.pl -t test1(或 test2test3

首先使用expand_term/2将DCG翻译为正则子句:

?- expand_term(match_test1 --> [t,e,s,t], Clause).
Clause =  (match_test1([t, e, s, t|_1498], _1498):-true).

然后在 Clause 上照常使用 assertz/1,即 assertz(Clause)

请注意,您可以直接写下原子,即不用 'e',只需写 e

此外,考虑通过添加指令将 double_quotes 设置为 chars

:- set_prolog_flag(double_quotes, chars).

现在可以写了,很方便:

?- T = "test".
T = [t, e, s, t].

这种语法非常好,使 DCG 更容易调试和使用。