0
votes

The following Prolog prints done for goals test1 and test2, but not test3. My understanding is that match_test2 and match_test3 in this code should be equivalent. How do I create a DCG rule via an assertion?

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").

Using SWI-Prolog version 7.2.3 for x86_64-darwin14.3.0, running as swipl -l bug.pl -t test1 (or test2, test3)

1

1 Answers

2
votes

Use expand_term/2 to translate the DCG to a regular clause first:

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

Then use assertz/1 as usual on Clause, i.e., assertz(Clause).

Note that you can write down the atoms directly, i.e., instead of 'e', simply write e.

In addition, consider setting double_quotes to chars by adding the directive:

:- set_prolog_flag(double_quotes, chars).

Now you can write, very conveniently:

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

This syntax is very nice and makes DCGs a lot easier to debug and work with.